Laravel with Vue.js
参考链接:
Laravel中使用vue.js实现前后端分离。Laravel 后端只提供 api供 Vue.js 前端调用。
Laravel 配置
1 | $ laravel new todo |
项目的入口 spa 视图1
$ php artisan make:controller SpaController
Http/Controllers/SpaController.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SpaController extends Controller
{
public function index()
{
// 项目的入口
return view('spa');
}
}
配置入口路由
routes/web.php1
2
3
// where()使用正则表达式匹配,.* 代表任何url都会被匹配
Route::get('/{any}', 'SpaController@index')->where('any', '.*');
入口视图 spa
resources/views/spa.blade.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue SPA Demo</title>
</head>
<body>
<div id="app">
<app></app>
</div>
<script src="{{ mix('js/app.js') }}"></script>
</body>
</html>
resources/js/app.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
import App from './views/App'
import Hello from './views/Hello'
import Home from './views/Home'
import UsersIndex from "./views/UsersIndex";
import UsersEdit from "./views/UsersEdit";
import NotFound from "./views/NotFound"
import UsersCreate from "./views/UsersCreate";
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/hello',
name: 'hello',
component: Hello,
},
{
path: '/users',
name: 'users.index',
component: UsersIndex,
},
{
path: '/users/:id/edit',
name: 'users.edit',
component: UsersEdit,
},
{
path: '/users/create',
name: 'users.create',
component: UsersCreate,
},
{
path: '/404',
name: '404',
component: NotFound,
},
{
path: '*',
redirect: '/404'
},
],
});
const app = new Vue({
el: '#app',
components: { App },
router,
});
resources/js/views/App.vue1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18<template>
<div>
<h1>Vue Router Demo App</h1>
<p>
<router-link :to="{ name: 'home' }">Home</router-link> |
<router-link :to="{ name: 'hello' }">Hello World</router-link>
<router-link :to="{ name: 'users.index' }">Users</router-link>
</p>
<div class="container">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {}
</script>
显示所有用户
用户数据填充
1 | $ php artisan make:seeder UsersTableSeeder |
database/seeds/UsersTableSeeder.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(App\User::class, 50)->create();
}
}
database/seeds/DatabaseSeeder.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
$this->call([
UsersTableSeeder::class,
]);
}
}
1 | $ php artisan migrate:refresh --seed |
Users 控制器
1 | $ php artisan make:controller Api/UsersController |
routes/api.php1
2
3
4
5
6
...
Route::namespace('Api')->group(function () {
Route::get('/users', 'UsersController@index');
});
app/Http/Controllers/Api/UsersController.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\User;
use App\Http\Resources\UserResource;
class UsersController extends Controller
{
public function index()
{
return UserResource::collection(User::paginate(10));
}
public function show(User $user)
{
return new UserResource($user);
}
public function update(User $user,Request $request)
{
$data = $request->validate([
'name' => 'required',
'email' => 'required|email',
]);
$user->update($data);
return new UserResource($user);
}
public function destroy(User $user)
{
$user->delete();
return response(null, 204);
}
public function store(Request $request)
{
$data = $request->validate([
'name' => 'required',
'email' => 'required|unique:users',
'password' => 'required|min:8',
]);
return new UserResource(User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
]));
}
}
UserIndex.vue 前端文件
Vue-router1
2
3
4
5
6
7// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
router.push({ name: 'user', params: { userId }}) // -> /user/123
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
分页的数据结构
resources/js/views/UsersIndex.vue1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132<template>
<div class="users">
<div v-if="error" class="error">
<p>{{ error }}</p>
</div>
<ul v-if="users">
<li v-for="{ id ,name, email } in users">
<strong>Name:</strong> {{ name }},
<strong>Email:</strong> {{ email }}
<router-link :to="{ name: 'users.edit',params: {id} }">Edit</router-link>
</li>
</ul>
<div class="pagination">
<button :disabled="! prevPage" @click.prevent="goToPrev">Previous</button>
{{ paginatonCount }}
<button :disabled="! nextPage" @click.prevent="goToNext">Next</button>
</div>
<div>
<router-link :to="{ name: 'users.create' }">Add User</router-link>
</div>
</div>
</template>
<script>
import axios from 'axios';
const getUsers = (page,callback)=> {
const params = { page };
axios
.get('/api/users',{params})
.then(response => {
callback(null, response.data);
}).catch(error => {
callback(error, error.response.data);
});
}
export default {
data() {
return {
//loading: false,
users: null,
// "meta": {
// "current_page": 1,
// "from": 1,
// "last_page": 5,
// "path":
// "per_page": 10,
// "to": 10,
// "total": 50
// }
meta: null,
links: {
first: null,
last: null,
next: null,
prev: null,
},
error: null,
};
},
computed: {
nextPage() {
if (!this.meta || this.meta.current_page ==
this.meta.last_page) {
return;
}
return this.meta.current_page + 1;
},
prevPage() {
if (!this.meta || this.meta.current_page ==
1) {
return;
}
return this.meta.current_page - 1;
},
paginatonCount() {
if (!this.meta) {
return;
}
const {current_page,last_page} = this.meta;
return `${current_page} of ${last_page}`;
},
},
beforeRouteEnter (to, from, next) {
getUsers(to.query.page, (err, data) => {
next(vm => vm.setData(err, data));
});
},
beforeRouteUpdate (to, from, next) {
this.users = this.links = this.meta = null
getUsers(to.query.page, (err, data) => {
this.setData(err, data);
next();
});
},
created() {
},
methods: {
goToNext() {
this.$router.push({
query: {
page: this.nextPage,
}
})
},
goToPrev() {
this.$router.push({
name: 'users.index',
query: {
page: this.prevPage,
}
});
},
setData(err, { data: users, links, meta }) {
if (err) {
this.error = err.toString();
} else {
this.users = users;
this.links = links;
this.meta = meta;
}
},
}
}
</script>