Laravel Vue SPA 起步
最新的laravel项目要求支持PHP7.1
所以请先配置好你的php环境
第一步 创建项目
laravel new vue-spa
第二步 进入项目目录,将.env.example 改为.env文件
执行以下命令 生成key, 下载前端依赖
cd vue-spa
php artisan key:generate
npm install
目录说明
/resources/assets/js/comments 下存放vue组件
/package.json 使用了laravel-mix和vue依赖
/webpack.mix.js 中定义了laravel-mix的配置路径如下:
mix.js('resources/assets/js/app.js', 'public/js')
.sass('resources/assets/sass/app.scss', 'public/css');
手工去除 /resources/assets/sass/app.scss中的google font 引用
安装vue-router
npm install vue-router --save
在/resources/assets/js/app.js中 引用vue-router
import VueRouter from 'vue-router';
Vue.use(VueRouter)
将/resources/assets/js/comments/ExampleComponent.vue将改为Home.vue
创建/resources/assets/js/routes.js文件 ,内容如下
import VueRouter from 'vue-router'
let routes = [
{
path : '/',
component : require('./components/Home')
}
]
export default new VueRouter({
routes
})
在/resources/assets/js/app.js中将routes引用进来
require('./bootstrap');
window.Vue = require('vue');
import VueRouter from 'vue-router';
Vue.use(VueRouter)
import router from './routes';
const app = new Vue({
el: '#app'
router
});
创建/resources/view/layout/master.blade.php文件,内容如下
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel Vue SPA</title>
<link ref="stylesheet" href="/css/app.css">
</head>
<body>
<div id="app">
<router-view></router-view>
</div>
<script src="/js/app.js"></script>
</body>
</html>
修改/routes/web.php
Route::get('/', function () {
return view('layouts.master');
});
执行命令
npm run watch
同理可以创建About.vue组建
在/resources/assets/js/routes.js中添加相应的路由
let routes = [
{
path : '/',
component : require('./components/Home')
},
{
path : '/about',
component : require('./components/About')
},
]
在/resources/view/layout/master.blade.php页面使用router-link 增加导航
<div id="app">
<nav>
<ul class="nav nav-pills pull-right">
<router-link to="/" tag="li">
<a >Home</a>
</router-link>
<router-link to="/about" tag="li">
<a >About</a>
</router-link>
</ul>
</nav>
<router-view></router-view>
</div>
这时候发现页面可以顺利链接,但是url上有# ,如果希望去除#可以进行以下操作:
在/resources/assets/js中 ,将mode设置为history
export default new VueRouter({
mode:'history',
routes
})
在/routes/web.php中设置如下
Route::any('{all}', function () {
return view('layouts.master');
})->where(['all'=>'.*']);
Laravel Vue SPA - 与后端交互
先生成一些数据
创建model post
php artisan make:model Post -m
创建post数据工厂
php artisan make:factory PostFactory --model=Post
到/database/migrations/2018_04_29_095636_create_posts_table.php中添加一些字段
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->unsignedInteger('user_id');
$table->timestamps();
});
}
到/database/migrations/2014_10_12_000000_create_users_table.php 中添加一个字段
$table->boolean('is_active')->default(false);
在.env中配置数据库连接
执行数据迁移命令
php artisan migrate
为Post 和 User 创建假数据 打开/database/facotries/PostFactory.php文件
$factory->define(App\Post::class, function (Faker $faker) {
return [
'title' => $faker->sentence,
'body' => $faker->paragraph,
'user_id' => factory(\App\User::class)->create()->id
];
});
定义 Post的model文件的fillable属性,打开/app/Post.php文件
class Post extends Model
{
protected $fillable = ['title','body','user_id'];
}
执行tinker命令
php artisan tinker
factory(App\Post::class)->make() //此命令会生成user数据,但不会填充post数据到数据库中
factory(App\Post::class,55)->create() //此命令将在数据库中插入55条数据post数据
创建Post Controller
php artisan make:controller PostController
在PostController中添加方法,打开/app/Http/Controllers/PostController.php
namespace App\Http\Controllers;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(){
return Post::paginate(7);
}
public function show(Post $post){
return $post;
}
}
在/routes/api.php中定义路由
//使用时加上api前缀 api/posts
Route::get('/posts','PostController@index');
Route::get('/posts/{post}','PostController@show');
在/resources/assets/sass/app.scss中定义css
.bs-callout h4{
margin-top:0;
margin-bottom:5px;
}
.bs-callout-danger h4{
color:#ce4844;
}
在/resources/assets/js/compontents/Home.vue中 用axios调用posts api
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">文章首页列表</div>
<div class="card-body">
<div v-for="post in posts" :key="post.id" class="bs-callout bs-callout-danger">
<h4>{{post.title}}</h4>
<p>{{post.body}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
axios.get('/api/posts').then(response => {
this.posts = response.data.data
})
},
data(){
return {
posts:[]
}
}
}
</script>
接下来定义Post详情页面
首先定义前端路由 打开文件/resources/assets/js/routes.js 添加路由 ,命名为post
{
path : '/posts/:id',
name : 'post',
component : require('./components/Post')
},
然后创建Post.vue文件 /resources/assets/js/components/Post.vue
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header"><h4>{{post.title}}</h4></div>
<div class="card-body">
<div class="bs-callout bs-callout-danger">
<p>{{post.body}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
mounted() {
axios.get('/api/posts/'+this.$route.params.id).then(response => {
this.post = response.data
})
},
data(){
return {
post:[]
}
}
}
</script>
将 /resources/assets/js/componentsHome.vue的连接改为
<div v-for="post in posts" :key="post.id" class="bs-callout bs-callout-danger">
<h4><router-link :to="{ name:'post',params:{ id: post.id} }">{{post.title}}</router-link></h4>
<p>{{post.body}}</p>
</div>
重构 Vue 组件目录
创建/resources/assets/js/pages目录,将Home.vue About.vue移动到/resources/assets/js/pages中