使用Laravel 和 Vue 構建一個簡單的SPA


本教程是作者自己在學習Laravel和Vue時的一些總結,有問題歡迎指正。

Laravel是PHP的一個框架,Vue是前端頁面的框架,這兩個框架如何結合起來構建一個SPA(Single Page Application)呢?流程大致分為下面三步:

  1. 頁面請求Laravel的一個路由
  2. 路由返回渲染一個包含了Vue的SPA框架
  3. 在上面渲染出來的框架中使用Vue來加載不同的頁面單元模塊

主要會學習使用到三個東西:

  1. laravel
  2. vue.js
  3. Vue-router
  4. axios

上面是一個簡單的流程圖,從圖中我們可以看到,當請求34的路由時,並不會再次請求后端的Laravel,而是前端渲染了。

說了這么多,我們開始寫代碼吧~

1. 安裝

composer create-project --prefer-dist laravel/laravel laravel-spa "5.6.*"
cd laravel-spa

npm install
npm install vue-router

安裝好laravelvue-router后,我們需要配置前端路由和路由對應的組件

2. 配置Vue Router

Vue Router中把route和vue組件做了一個映射,在渲染時會把不同的組件渲染到<router-view></router-view>標簽中。

首先,我們修改resources/assets/js/app.js這個文件:

window.Vue = require('vue');
// 或者
import Vue from 'vue'

import VueRouter from 'vue-router'
// 引入Vue Router並加載到Vue中
Vue.use(VueRouter)

// 引入我們要使用到的幾個組件
import App from './views/App'
import Hello from './views/Hello'
import Home from './views/Home'

// 實例化一個Vue Router
const router = new VueRouter({
    mode: 'history',
    base: '/spa',
    routes: [
        {
            path: '/',	// 這是路徑
            name: 'home',	// 這是名稱
            component: Home // 這是使用的組件
        },
        {
            path: '/hello',
            name: 'hello',
            component: Hello
        }
    ],
});

// 注入Vue Router 實例,我們就能在vue里面這樣使用: this.$router, this.$route
const app = new Vue({
    el: '#app',
    components: { App, },
    router 
});

然后,新建以下幾個文件:

mkdir resources/assets/js/views
touch resources/assets/js/views/App.vue
touch resources/assets/js/views/Home.vue
touch resources/assets/js/views/Hello.vue

App.vue是所有組件的父組件,負責渲染其他頁面,代碼如下:

<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> |
        </p>

        <div class="container">
            <router-view></router-view>
        </div>
    </div>
</template>
<script>
    export default {}
</script>

注意這個router-view標簽,Vue Router會將組件渲染到該標簽里面。其他幾個頁面就是我們需要展示的組件頁面了。

Home.vue :

<template>
  <p>This is the homepage</p>
</template>

Hello.vue :

<template>
    <p>Hello World!</p>
</template>

現在的目錄結構是把頁面的模版和組件模版放在同一個目錄里面的,為了方便管理,我們可以把重用的組件單獨放一個component目錄里。

3. 后端代碼

SPA應用主要是以接口的形式請求的,后端在接收到頁面請求時不需要做過多的處理,代碼也很簡單,routes/web.php修改如下,刪除了原來的/路由:

Route::get('/{any}', 'SpaController@index')->where('any', '.*');

創建一個SpaController

php artisan make:controller SpaController

SpaConrtollerindex方法中我們直接返回需要渲染的模版:

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class SpaController extends Controller
{
    public function index()
    {
        return view('spa');
    }
}

最后,編輯resources/views/spa.blade.php模版:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Laravel Vue SPA Demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
    <div id="app">
        <app></app>
    </div>
</body>

<script src="{{ mix('js/app.js') }}"></script>
</html>

基本完成,現在來看看效果,因為laravel已經集成了一些前端開發的腳手架,可以說非常友好了,所以在寫好前端的組件后,運行如下命令就能打包前端代碼了:

npm run watch



現在我們簡單的SPA靜態頁面已經搭建完成了,可以看到當切換URL時,整個頁面的主題和菜單並沒有換,更新的只是下面的內容,接下來我們是這調用后端的API。

4. 編寫一個測試API

由於是測試,后端代碼很簡單,就幾行,routes/api.php修改如下:

Route::get('/users', function () {
    return factory('App\User', 10)->make();
});

上面就是我們編寫的一個簡單接口,我么直接在路由中使用了Laravel現成的User模型mock10條數據,注意,由於Laravel中webapi是單獨分開的,所以在訪問api接口時需要加上/api前綴,分析`App\Providers

\RouteServiceProvider`文件就能看出來:

/**
 * Define the "api" routes for the application.
 *
 * These routes are typically stateless.
 *
 * @return void
 */
protected function mapApiRoutes()
{
    Route::prefix('api')
         ->middleware('api')
         ->namespace($this->namespace)
         ->group(base_path('routes/api.php'));
}

我們試着訪問下接口:

接口寫好,現在我們需要在前端用axios調用我們的接口。

5. axios上手

現在回到我們Vue Router的配置中,添加一個組件並定義一個新的路由:

…
import UsersIndex from './views/UsersIndex'
…

const router = new VueRouter({
    mode: 'history',
    base: '/',
    routes: [
        {
            path: '/',
            name: 'home',
            component: Home
        },
        {
            path: '/hello',
            name: 'hello',
            component: Hello
        },
        {
            path: '/users',
            name: 'users.index',
            component: UsersIndex
        }
    ],
});

實現UsersIndex組件:

<template>
    <div class="users">
        <div v-if="loading" class="loading">Loading</div>
        <div v-if="error" class="error">
            <p>{{ error }}</p>

            <p><button @click.prevent="fetchData">Try again</button></p>
        </div>

        <ul v-if="users">
            <li v-for="{name, email} in users" @key="name">
                <strong>Name: </strong>{{ name }},
                <strong>Email: </strong>{{ email }}
            </li>
        </ul>
    </div>
</template>

<script>
import axios from 'axios';

export default {
    data() {
        return {
            loading: false,
            users: null,
            error: null,
        };
    },
    created() {
        this.fetchData()
    },
    methods: {
        fetchData() {
            this.error = this.users = null;
            this.loading = true;
            axios.get('/api/users')
                .then(response => {
                    this.loading = false;
                    this.users = response.data;
                })
                .catch(error => {
                    this.loading = false;
                    this.error = error.response.data.message || error.message;
                })
        }
    }
}
</script>

這個Vue的組件很簡單,說說fetchData這個方法,使用了axiosget我們寫好的后端接口,將得到的數據用Vue在前端渲染出來,看看效果:

我們成功獲取到了后端數據,並在前端渲染出來。到此,我們現在已經了解了開發SPA應用的簡單流程。

6. 最后再來個總結吧

使用SPA有什么好處呢?第一,不同頁面之前切換時不會有明顯的變化,至少整個頁面框架不會切換,前端再配合一個loading動畫,會更加友好,而全部用服務端渲染,頁面在切換時會有一段時間的頁面空白現象,在網速不理想的情況下空白的時間會更長。第二,職責更加清晰,SPA應用完全是前后端分離,后端只需要認真編寫接口,前端只要獲取並渲染,開發人員不需要同時看后端代碼和前端代碼,職責清晰的同時保證了碼代碼的效率,第三,SPA是無狀態的,不需要管理session

參考 :
https://laravel-news.com/using-vue-router-laravel
https://router.vuejs.org/zh/


👏文章首發【正義的程序猿】,歡迎大家關注哦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM