上次我用 laravel5.3 + Vue
開發了一個簡單的單頁應用,此次我打算將其升級到 laravel5.5
,在升級的過程當中,作一下記錄,其源碼放在 github
上面,源碼地址javascript
軟件包 | 版本 |
---|---|
Laravel | 5.5 |
Vue | > 2.5.7 |
axios | > 0.17 |
vue-router | > 3.0.1 |
vuex | > 3.0.1 |
# 安裝 laravel composer create-project --prefer-dist laravel/laravel laravel-vue "5.5.*" # 安裝前端依賴包 npm install
安裝完以後,爲了便於開發,使用熱更新模式。php
# 在 webpack.mix.js 中添加配置 mix.browserSync({ proxy: 'localhost:8000' }); # 執行 `php artisan serve` php artisan serve # 執行 npm run watch npm run watch
打開瀏覽器訪問 http://localhost:3000
就能夠看到 laravel
的歡迎頁面了css
開發三個頁面,首頁,列表,詳情,相對應準備 3 個 api
接口html
php artisan make:migration news --create=news
# database/migrations/create_news.php Schema::create('news', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('content'); $table->integer('is_recommend')->default(0); $table->timestamps(); });
這裏使用命令生成 model
文件,編輯對應的文件內容。前端
php artisan make:model News
# app/News.php namespace App; use Illuminate\Database\Eloquent\Model; class News extends Model { public $fillable = ['title', 'content']; }
生成控制器,在控制器中定義三個接口對應的方法。vue
php artisan make:controller NewsController
# app/Http/Controllers/NewsController <?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\News; class NewsController extends Controller { /** * 推薦列表 */ public function recommend() { $list = News::where('is_recommend', 1)->get(); foreach ($list as $key => $value) { $list[$key]->created = $list[$key]->created_at->diffForHumans(); } return $list; } /** * 新聞列表 */ public function index() { $list = News::get(); foreach ($list as $key => $value) { $list[$key]->created = $list[$key]->created_at->diffForHumans(); } return $list; } /** * 新聞詳情 */ public function show($id) { $row = News::findOrFail($id); return $row; } }
定義 api
的接口路由,在 routes/api.php
文件中定義。java
# routes/api.php Route::get('/news', 'NewsController@index'); Route::get('/news/recommend', 'NewsController@recommend'); Route::get('/news/{id}', 'NewsController@show');
到這裏咱們準備工做已經完畢,接下來正式開發 Vue
的單頁應用,在開發單頁應用中,對應 Route
Api
Vuex
Components
這些,下面咱們就來定義這些。webpack
首先在首頁引入對應的 app.css
和 app.js
文件。ios
# resource/vies/welcome.blade.php
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="csrf-token" content="@{{ csrf_token }}"> <title>Laravel & Vue</title> <link rel="stylesheet" type="text/css" href="/css/app.css"> </head> <body> <div id="app"> <nav class="navbar navbar-inverse"> <div class=" container"> <div class="navbar-header"> <a class="navbar-brand" href="/">LaravelVue</a> </div> </div> </nav> <div class="container main"> <router-view /> </div> </div> <script type="text/javascript" src="/js/app.js"></script> </body> </html>
應用對應的入口文件是 app.js,因此在這個入口文件中,咱們實例化 Vue
實例,初始化和加載所需的組件。laravel
# resource/assets/js/app.js require('./bootstrap'); window.Vue = require('vue'); import VueRouter from 'vue-router'; Vue.use(VueRouter); import store from './store/'; // vuex 數據存儲所需對象 import routes from './routes'; // 路由配置文件 // 實例化路由 const router = new VueRouter({ routes }) var vm = new Vue({ store, router }).$mount('#app');
前端頁面主要有 3 個路由,以下
# resource/assets/js/routes.js export default[ { path: '', redirect: '/index' }, { path: '/index', component: require('./page/App.vue') }, { path: '/list', component: require('./page/List.vue') }, { path: '/detail/:id', component: require('./page/Detail.vue') } ];
Vuex
集中式存儲管理應用的全部組件的狀態,這裏使用的是多模塊方式記錄數據。
# resource/assets/js/store/index.js import Vue from 'vue'; import Vuex from 'vuex'; import news from './news'; Vue.use(Vuex); export default new Vuex.Store({ // 能夠設置多個模塊 modules: { news } }); # resource/assets/js/store/news.js import api from '../api'; export default{ state: { recommend: [], // 推薦 lists: [], // 列表 detail: {} // 詳情 }, mutations: { // 注意,這裏能夠設置 state 屬性,可是不能異步調用,異步操做寫到 actions 中 SETRECOMMEND(state, lists) { state.recommend = lists; }, SETLISTS(state, lists) { state.lists = lists; }, SETDETAIL(state, detail) { state.detail = detail; } }, actions: { getNewsDetail({commit}, id) { // 獲取詳情,並調用 mutations 設置 detail api.getNewsDetail(id).then(function(res) { commit('SETDETAIL', res.data); document.body.scrollTop = 0; }); }, getNewsRecommend({commit}) { api.getNewsRecommend().then(function(res) { commit('SETRECOMMEND', res.data); }); }, getNewsLists({commit}) { api.getNewsLists().then(function(res) { commit('SETLISTS', res.data); }); } } }
咱們在這裏定義前端請求數據 api
,這裏使用的是 axios
包來請求數據,具體用法參考文檔。
# resource/assets/js/api.js import axios from 'axios' export default { // 首頁推薦接口 getNewsRecommend: function (params) { return axios.get('api/news/recommend', { params: params }) }, // 列表接口 getNewsLists: function (params) { return axios.get('api/news', { params: params }) }, // 詳情接口 getNewsDetail: function (id) { return axios.get('api/news/' + id) } }
咱們在這裏定義組件頁面,將其頁面放到 page
目錄下面,Vue
定義組件的方式參考文檔。
三個頁面的具體寫法定義以下:
# resource/assets/js/page/App.vue
<template> <div class="panel panel-default"> <div class="panel-heading">新聞推薦 <router-link to="/list" class="pull-right">更多</router-link> </div> <ul class="list-group"> <li class="list-group-item" v-for="row in recommend"> <router-link :to="{path:'/detail/' + row.id}"> {{ row.title }} </router-link> <span class="pull-right">{{ row.created }}</span> </li> </ul> </div> </template> <script> import { mapState, mapActions } from 'vuex'; export default({ // 映射 vuex 上面的屬性 computed: mapState({ recommend: state => state.news.recommend }), created() { // 獲取推薦列表 this.getNewsRecommend(); }, methods: { // 映射 vuex 對象上的方法 ...mapActions([ 'getNewsRecommend' ]) } }); </script> # resource/assets/js/page/List.vue <template> <div class="panel panel-default"> <div class="panel-heading">新聞列表</div> <ul class="list-group"> <li class="list-group-item" v-for="row in lists"> <router-link :to="{path:'/detail/' + row.id}"> <span class="label label-success" v-if="row.is_recommend">推薦</span> {{ row.title }}