# 17. 百頁路由

# 單頁式網頁與路由器

使用單頁式網頁的目的:

  • 節省載入時間
  • 動畫過場效果

在單頁式網頁中,網址和頁面的切換可透過路由器來實現。

  • 使用路由器切換網址、控制顯示哪些組件。
  • 在本機的網址中,用 # 可以讓瀏覽器不換頁。

# 加入 vue-router

透過終端機在 Vue CLI 加入 vue-router:

vue add router

執行成功之後,會看到專案資料夾中會有些檔案的變動 (修改、新增)。

# 異動:調整 main.js

加入 vue-router 之後,main.js 檔案的和原本的差異:

  • 透過 import 載入 "router.js"。
  • 將 router 放到 new Vue 裡面。
import Vue from 'vue'
import App from './App.vue'
import router from './router'    // 載入 router.js

Vue.config.productionTip = false

new Vue({
  router,                        // 將 router 放到 Vue
  render: h => h(App)
}).$mount('#app')

# 異動:新增 router.js

router.js 用來定義此專案有哪些路徑,這些路徑會對應到哪一個 component。

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  // 第一種載入方法
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  // 第二種載入方法
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

在上方預設的程式碼中,展現了兩個路徑 (Home、About),以及路由的兩種載入方法。

# 載入方法一

  1. 先用 import 載入。
  2. 然後掛載到 router。
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
]

# 載入方法二

  • 直接在 router 裡面透過函式 import 新的 component。
const routes = [
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

# 兩種方法的差異

在預設的程式碼中,"Home" 頁面使用方法一載入,"About" 頁面使用方法二載入。

如果透過方法二載入頁面,會依照 router 把程式碼分割開來。點擊連結進入頁面時,才會真正將那個頁面載入進來,可節省一開始網頁的讀取時間。但相對來說,缺點就是會比方法一多讀取一次網頁。

使用開發人員工具來看 "Network" 的部分,會看到一開始載入 Home 頁面時,使用方法二的 "about.js" 狀態碼會是 304。

等到點擊了畫面中的 "About" 連結時, "about.js" 會再載入一次,而且這次的狀態碼會是 200。

這是因為 Vue 產生 prefetch 預備讀取,所以一開始的 "about.js" 才會是 304 狀態碼,以達到分檔、分別讀取的效果。

至於選擇何種方法載入 component,要看專案大小。如果專案較大,要載入的東西多,則適合使用方法二。

# 異動:修改 App.vue

原本的主畫面中,template 會藉由以下兩個標籤控制畫面:

  • router-link 用來切換畫面的連結按鈕。
  • router-view 顯示被選擇的 router-link 的內容。
<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link>|
      <router-link to="/about">About</router-link>
    </div>
    <router-view />
  </div>
</template>

# 增加新路徑和畫面的步驟

新增步驟:

  1. 新增畫面 component
  2. 載入到 "router.js"
  3. 在主畫面 "App.vue" 加上路徑連結

# 1. 新增畫面 component

  • 在 src > views 資料夾中,新增副檔名為 vue 的 component。
  • 在此新檔案中撰寫程式碼。
  • 要注意 component 的 template 最外面只能有一層 DOM。
//- Hello.vue

<template>
  <h1>Hello, this is Hello.vue component.</h1>
</template>

# 2. 載入到 "router.js"

  • 將新的 component 載入到 "router.js",並掛載到 router 裡面。
  • 如果成功,在網址列後方修改為新 component 的路徑,就會看到 component 的內容。
//- router.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Hello from '../views/Hello.vue' // 使用方法一載入新路徑

Vue.use(VueRouter)

const routes = [{
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import( /* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/hello',   // 掛載新的 Hello.vue 路徑到 router
    name: 'Hello',
    component: Hello
  },
]

// ...

# 3. 在主畫面 "App.vue" 加上路徑連結

  • 到 "App.vue" 增加 router-link,為主畫面加上通往新 component 的連結。
//- App.vue

<template>
  <div id="app">
    <div id="nav">
      <router-link to="/">Home</router-link>|
      <router-link to="/about">About</router-link>|
      <router-link to="/hello">Hello</router-link>   // 加入新連結
    </div>
    <router-view />
  </div>
</template>

結果如下:

Vue 內建了兩個 class ,可以讓我們拿來修改 router-link 的樣式。

  • router-link-active
    • 表示路由的過程、被經過的路由。較少被使用。
    • 如果切換到 /about,則路徑為 / 的首頁也會套用到樣式。
  • router-link-exact-active
    • 表示目前所在的頁面,較常被使用。