Vue.js (11) - 在 Laravel 5.4 中使用 Vue 2.1

Vue.js

Laravel 在第 5 版時已經內建支援 Vue,這篇將簡單介紹如何使用它們一起工作。
註:這裡使用的 Laravel 版本為 5.4.23,Vue 版本為 2.1.10。

新專案

這裡假設的情況為從無到有建立一個 Laravel 專案,請自行略過你已經做的部份:

1. 安裝 Composer

請參考 使用 Composer 管理 PHP 套件

2. 安裝 Laravel Installer

在 shell 中執行:
composer global require "laravel/installer"
安裝完成後,將 你的使用者家目錄/.composer/vendor/bin 路徑加入 $PATH 中。執行 laravel -v 確認指令可以執行。

3. 建立新專案

laravel new laravel-vue
laravel-vue 是專案名稱,可自定。

4. 啟動伺服器

請自行選擇以下方式:
  • 方式 1:使用 XAMPPMAMPWAMP 等等開發環境。
  • 方式 2:使用 HomesteadValet(Mac)
  • 方式 3:使用內建伺服器:直接在專案目錄下執行
    php artisan serve
    就可以在 http://127.0.0.1:8000 看到網站內容。
為了示範方便,我們選擇方式 3。確定你可以看到 Laravel 的預設首頁。

5. 安裝相依套件

當我們建立新專案時,Laravel 需要使用的 PHP 相關套件已經安裝好了,可以在 vender 目錄中看到。如果你是使用別的方式建立專案,而相依套件還沒裝的話,可以執行
composer install
它會依 composer.jsoncomposer.lock 來安裝相依套件。

另外,還必須安裝 JavaScript 的相依套件,請執行
npm install
或
yarn
它會依 package.json 來安裝相依套件,安裝好的套件會放在 node_modules 目錄。

使用 Vue 單一元件檔

接下來我們會在這個新專案中使用 Vue 單一元件檔來建立網頁。

1. 編輯 routes/web.php

PHPRoute::get('/', function () {
    return view('hello');
});
我們的首頁將會顯示 hello 這個頁面。

2. 新增 resources/views/hello.blade.php

HTML<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Hello</title>
</head>
<body>
    <!-- 準備給 Vue 的掛載點 -->
    <div id="app">
        <!-- 使用我們建立的元件,
             一個有傳入名字,一個沒有 -->
        <Hello name="Tony"></Hello>
        <Hello></Hello>
    </div>
    <!-- 載入打包後的 js 檔 -->
    <script src="/js/hello.js"></script>
</body>
</html>
這只是一個很簡單的 HTML5 頁面,其中用到等一下我們要建立的 <Hello></Hello> 元件,還有會匯出該元件的 hello.js

3. 新增 resources/assets/js/components/Hello.vue

HTML<template>
    <div>
        <h1>Hello</h1>
        <p class="hello">Hi {{ name || '匿名' }}</p>
        <p>{{ msg }}</p>
    </div>
</template>

<script>
    export default {
        props: ['name'],
        data () {
            return {
                msg: 'This is a Laravel with Vue Demo.'
            }
        }
    }
</script>

<style>
.hello {
    font-size: 2em;
    color: green;
}
</style>
內容很簡單的一個 vue 元件檔。props 設定的名稱可以讓父元件傳資料進來。

4. 看一下 resources/assets/js/bootstrap.js

檢查一下這個檔案裡是否有建立 Vue 的全域變數(可能沒有),我們把它加入:
window.Vue = require('vue');
這樣之後使用 Vue 就不需要再 import 或 require 了。

5. 新增 resources/assets/js/hello.js

JavaScriptrequire('./bootstrap');

// 匯入 Hello.vue 檔,不需加副檔名
import Hello from './components/Hello'

new Vue({
    // 找到 hello.blade.php 中指定的掛載點元素
    el: '#app',
  
    // 使用我們建立的 Hello(.vue) 元件
    components: { Hello }
})
這個檔案被打包後,會在 hello.blade.php 中被使用。

以上程式的部份就寫完了,總共會建立 3 個檔案:
  1. hello.blade.php:Laravel 的樣板檔。
  2. Hello.vue:Vue 單一元件檔。
  3. hello.js:建立 Vue 實體及設定 Vue 元件。

6. 修改 webpack.mix.js

接下來就是打包了,打包的動作會把 .vue 元件檔.js 檔 編譯成一個獨立的 .js 檔,而由於我們有 require('./bootstrap'); 所以其中要求的 js 套件也會一併被打包。

Laravel 在 5.4 版加入了 Mix,比之前的 Laravel Elixir 更簡單好用,它使用 Webpack 來執行打包,設定檔就在專案根目錄下的 webpack.mix.js,我們修改後內容如下:
const { mix } = require('laravel-mix');
mix.js('resources/assets/js/hello.js', 'public/js');
只有兩行,目標是把 resources/assets/js/hello.js 打包後放到 public/js/hello.js

7. 打包並執行

在 shell 中,切換到專案根目錄,執行以下指令:
npm run dev
或
yarn run dev
這樣就打包完成。接著來啟動內建伺服器,一樣在專案根目錄:
php artisan serve
順利的話,在瀏覽器 http://127.0.0.1:8000 上應該可以看到頁面的結果。指令執行後會停滯,請不要再繼續執行指令,可以用 Ctrl + C 來終止。

自動打包

因為我們必須執行打包的動作,才能在網站看到結果,如果在開發中不斷執行 run dev 實在太沒效率,我們可以改用
npm run watch
或
yarn run watch
這個指令執行後會一樣會停滯,請不要再繼續執行指令,可以用 Ctrl + C 來終止。

發佈

如果你開啟 public/js/hello.js 檔案來看的話,它是尚未被壓縮的內容,而且因為加入了其他套件,檔案會有 1MB 多,這可不能拿來給實際的產品用。當你的網站開發告一段落,要發佈到產品伺服器上,必須使用
npm run prod
或
yarn run prod
來進行打包並壓縮,這時你可以開啟檔案來看看差別,並比較檔案大小是不是小了許多。

抽取套件

通常你的網站不會只有一頁,因此你會在不同的頁面建立不同的 .vue 及 .js 檔,但是它們都是使用同一些套件,於是當你打包時,這些相同的套件就被重覆打包在不同的 .js 檔中,這樣不僅浪費使用者下載的頻寬及載入速度,也無法善用瀏覽器的快取功能。

我們可以將這些會重覆使用的套件抽取出來獨立成一個檔案,這樣只會在第一次載入時花多一點時間,之後瀏覽器就可以從快取中讀取,不會重覆下載相同的內容。

先來看看我們用了哪些套件,打開 resources/assets/js/bootstrap.js,看看全域變數請求了哪些套件,有 lodashjqueryaxios 及我們加入的 vue,我們將要把這些套件抽取成為一個獨立檔案。

首先,編輯 webpack.mix.js,使用 extract 指令來指定要抽取的套件:
mix.js('resources/assets/js/hello.js', 'public/js')
   .extract(['lodash','jquery','axios','vue']);
這樣當你執行打包時,就會產出 2 個額外檔案及 1 個我們自己寫的檔案:
  • public/js/manifest.js: Webpack manifest runtime
  • public/js/vendor.js: 使用的套件全部綁成一包
  • public/js/hello.js: 你自己的 js 檔,這裡是 hello.js
你可以看看 hello.js 的內容及檔案大小是不是和之前的不一樣了。

接下來,我們要稍微調整一下 resources/views/hello.blade.php 有關 <script> 的部份:
HTML<script src="/js/manifest.js"></script>
<script src="/js/vendor.js"></script>
<script src="/js/hello.js"></script>
!!重要!! 為了避免 JavaScript 執行時發生錯誤,務必使用以上的匯入順序,你自己寫的 js 永遠是最後載入。

這樣就完成套件的抽取。不過,在 Laravel 中,我們通常會使用 Layout 檔將頁面中相同的部份抽離,以下將示範如何在共用的 Layout 中使用抽取套件。

Laravel Layout 使用範例

假設你有一個 Layout 檔 resources/views/layouts/default.blade.php
HTML<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>@yield('title')</title>
</head>
<body>
    <div id="app">
        @yield('content')
    </div>
    <script src="/js/manifest.js"></script>
    <script src="/js/vendor.js"></script>
    @yield('script')
</body>
</html>
我們指定了 3 個準備填入內容的 titlecontentscript 區塊。

接著修改 resources/views/hello.blade.php
HTML@extends('layouts.default')

@section('title', 'Laravel With Vue Demo')

@section('content')
    <Hello name="Tony"></Hello>
    <Hello></Hello>
@endsection

@section('script')
    <script src="/js/hello.js"></script>
@endsection
只要使用同一個 Layout 的頁面,內容就會差不多是這樣,並且原本寫在這裡的程式碼,也全都改到 .vue 中了。假如規劃的夠好,當未來需要修改某個內容時,很可能只需動到某一個 .vue 檔或是抽換成另一個 .vue 檔就可以了。
本文網址:http://blog.tonycube.com/2017/06/vuejs11-laravel-vue.html
Tony Blog 撰寫,請勿全文複製,轉載時請註明出處及連結,謝謝 😀

11 則留言

  1. 請問 步驟5 的 npm install 後面要加東西嗎? 因為我下完命令好像建了很多資料夾,謝謝

    回覆刪除
    回覆
    1. 不用,你可以看 package.json 這個檔案,
      npm install 會將它指定的套件下載到 node_modules 資料夾下,
      各自的套件會有各自的資料夾,由於每個套件又會相依其他套件,
      所以可能會有超多的資料夾。

      刪除
  2. Tony 哥您好,
    請問這裡的 lodash 有什麼作用呢?

    原本都是寫前後端分離的 Vue,目前到新的工作崗位竟然是在 laravel 下寫Vue~
    所以有一些地方不太懂,謝謝。

    回覆刪除
    回覆
    1. lodash 是一個 JavaScript 的工具套件,主要是讓你在處理陣列、物件及字串等等資料時更加容易,你可以看看它的文件 https://lodash.com/ 或 https://github.com/lodash/lodash

      這裡的 lodash 應該只是用來舉例如何「抽取套件」用的,太久以前寫的文章,有點忘了 😬

      刪除
  3. Tony 哥你好

    我透過你這篇文章解決了一些問題

    原本寫Vue純前端,但因工作需求在laravel寫Vue困擾我一個月了

    請問能否讓我小額贊助表達感謝呢?

    回覆刪除
    回覆
    1. 我寫的文能幫到忙我就很開心了,在心裡接受你的贊助啦~謝謝 :)

      刪除
  4. 您好,請教 Tony 哥

    如何讓Vue components呈現在預設的blade extend layout 裡面而不是外面呢?
    透過前幾篇文章的分享,學會了 blade 的一些語法和佈局觀念,所以我把每個網頁會呈現的 header、footer 用 extend layout的方式呈現,
    但問題來了,每個掛載到 blade 的 Vue Components 都是在 blade extend layout 上面而不是在 blade extend layout 下面,也就是 component 的位置都是在 header block 上面。

    謝謝!

    回覆刪除
    回覆
    1. 不是很懂。你可以把自己的 blade 檔和 Vue 元件的相對位置畫在紙上,看看位置對不對,是不是你想要的結構。

      刪除

留言小提醒:
1.回覆時間通常在晚上,如果太忙可能要等幾天。
2.請先瀏覽一下其他人的留言,也許有人問過同樣的問題。
3.程式碼請先將它編碼後再貼上。(線上編碼:http://bit.ly/1DL6yog)
4.文字請加上標點符號及斷行,難以閱讀者恕難回覆。
5.感謝您的留言,您的問題也可能幫助到其他有相同問題的人。