[Express+Vue 搭建電商網站] 02 - vue-router 的使用
使用 Express + Vue 搭建一個電商網站 - vue-router 的使用
在接下來的內容中會學習 vue-router 的使用方法與學習路由基礎知識
並使用 vue-router 來進行多個頁面的跳轉
建立新組件
首先我們要先建立新的頁面組件,新建一個 src/components/Home.vue
檔案
<template>
<div>
<div class="title">
<h1>{{msg}}</h1>
</div>
</div>
</template>
<script>
export default {
name: 'home',
data () {
return {
msg: 'Welcome to Your Vue.js App'
};
},
}
</script>
看起來跟一開始預設的 HelloWorld.vue
有 87% 像,但是這邊先不對樣式做糾結,之後再去找 UI 庫套用
設定 vue-router
在安裝了 vue-router 之後,會發現專案中多了一個資料夾 /src/router/index.js
這就是 vue-router 的設定檔
藉由以下這段我們發現,路徑 '/'
使用的是 Home
這個組件
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')
}
]
順著邏輯往上找會發現 Home 這個組件的引用來源
import Home from '../views/Home.vue'
接著打開 /views/Home.vue
,原來這引入了 HelloWorld 組件
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'Home',
components: {
HelloWorld
}
}
</script>
知道原理之後呢,就把 /views/Home.vue
內部目前沒有用到的部分刪除,並且換成我們上面建立的 Home 組件
<script>
// @ is an alias to /src
import Home from '@/components/Home.vue'
export default {
name: 'Home',
components: {
Home
}
}
</script>
這時候使用瀏覽器開啟專案首頁,應該就會看到首頁已經變成 Home.vue
的內容
加入頁面上方導航超連結
打開 App.vue
檔案,在 id="app"
中加入三個 router-link
標籤的超連結,這是 Vue Router 的 API
根據官網說明 <router-link>
比起寫死的 <a href="...">
會好一些
- 無論是 HTML5 history 模式還是 hash 模式,它的表現行為一致,所以,當你要切換路由模式,或者在 IE9 降級使用 hash 模式,無須作任何變動。
- 在 HTML5 history 模式下,router-link 會守衛點擊事件,讓瀏覽器不再重新加載頁面。
- 當你在 HTML5 history 模式下使用 base 選項之後,所有的 to 屬性都不需要寫 (基路徑) 了。
<template>
<div id="app">
<nav>
<div class="container">
<ul class="nav__left">
<li>
<router-link to="/">Home</router-link>
</li>
<li>
<router-link to="/admin">Admin</router-link>
</li>
<li>
<router-link to="/cart">Cart</router-link>
</li>
</ul>
</div>
</nav>
<router-view/>
</div>
</template>
看到上面的程式碼內容,聰明的你一定知道接著我們要建立三個頁面
- admin 後台管理
- 購物車頁面
剛剛示範了怎麼在 /views/Home.vue
中引入 src/components/Home.vue
但在這邊先簡單一點,直接在 /views/
目錄下建立如同 src/components/Home.vue
內容的檔案
這時候 /views/
資料夾應該會長得像這樣
這時候其實可以把剛剛的 Home.vue
搬移進 /views/
中,我們原本的引用在這邊有點多此一舉了
但是在搬移過後會發現瀏覽器提示我們發生了一些問題,原來是 Home.vue 找不到檔案,但是為什麼呢?
我們不是在 vue-router 裡面指定路徑 ‘/‘ 要到 Home.vue
嗎?
首先復原程式碼,來看看在哪裡使用到了 src/components/Home.vue
?
哈!原來是一開始我們創建新組建時候把 App.vue
裡面的初始頁面 import 設定成 Home
這也就說明了為什麼在 admin 以及 Cart 頁面中 Home.vue 的內容還是陰魂不散
在刪除 import 的內容之後一切就正常了
新建立的頁面加入路由
接著把剛剛新建的頁面加入路由設定檔案 /src/router/index.js
中
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home.vue'
import Admin from '@/views/Admin';
import Cart from '@/views/Cart';
Vue.use(Router)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/admin',
name: 'Admin',
component: Admin
},
{
path: '/cart',
name: 'Cart',
component: Cart,
},
]
const router = new Router({
routes
})
export default router
好像有些什麼東西怪怪的?為什麼可以用 @
引用東西呢?代表什麼意思?
在我深入研究後發這是一個 webpack 的設定
存在於 \node_modules\@vue\cli-service\lib\config\base.js
進入檔案之後可以發現有設定了一個 alias set('@', api.resolve('src'))
這代表告訴了 vue
看到路徑用 @ 開頭的,就從 src 這個目錄開始操作
這樣做可以大幅度的減少我們使用 ../
這種作法造成目錄結構變換就專案大爆炸,或是為了存取深層的檔案,畫面被一堆點點斜線佔滿
在完成了以上動作之後,打開瀏覽器預覽一下
看來我們剛剛完成了一個簡單的基於 Vue 的多頁面網站了!
嵌套路由
有點經驗的工程師就知道,路由絕對不是這麼簡單的
當頁面少的時候可以全塞在一支檔案裡面,但當頁面開始多這樣就會顯得很亂,並且無法一眼看出彼此之間的階層關聯
還好 vue-router 提供了嵌套路由的功能,讓我們可以組織化的管理相關聯的頁面
在後台頁面中會使用到很多操作的頁面,例如新增、修改商品,下面就藉由嵌套路由的方法來管理這些路由
在引入的地方加入我們之後要增加的頁面,這邊只是先聲明,之後會一步一步的完成頁面
// Admin Components
import Index from '@/views/admin/Index'
import New from '@/views/admin/New'
import Products from '@/views/admin/Products'
import Edit from '@/views/admin/Edit'
路由常數中加入嵌套路由,會發現 Admin
下有四個組件(component)
而嵌套路由會為相關連的子路由設置一個入口頁面
然後把這些頁面都放到 children
定義中的陣列中
{
path: '/admin',
name: 'Admin',
component: Index,
children: [
{
path: '',
name: 'Products',
component: Products,
},
{
path: 'new',
name: 'New',
component: New,
},
{
path: 'edit/:id',
name: 'Edit',
component: Edit,
},
]
},
接著回到 /src/views/admin
建立
- Index.vue
- Edit.vue
- New.vue
- Products.vue
Index.vue
Index
是我們上面提到的入口組件,也就是渲染 path = /admin
的基礎組件
其餘的組件藉由 children
陣列宣告為嵌套的子路由。在子路由內的路由,前端都必須加上父層的路徑
而在上方的定義中,我們把 /admin/
的渲染子組件定義給了 Products
<template>
<div>
<div class="admin-new">
<div class="container">
<div class="col-lg-3 col-md-3 col-sm-12 col-xs-12">
<ul class="admin-menu">
<li>
<router-link to="/admin">View Products</router-link>
</li>
<li>
<router-link to="/admin/new">New Products</router-link>
</li>
</ul>
</div>
<router-view></router-view>
</div>
</div>
</div>
</template>
<router-view></router-view>
是用來渲染子路由的組件,比如說我們進入了 admin/new
那麼 <router-view></router-view>
內部會被替換成 New.vue
組件的內容
因為我們在上面路由定義中定義 ‘/new’ 的路由渲染組件是 New.vue
Edit.vue
<template>
<div>
<div class="title">
<h1>This is Admin/Edit/{{$route.params.id}}</h1>
</div>
</div>
</template>
Edit
這個路由在剛剛路由定義的時候有點不一樣,他的路徑是 edit/:id
這種寫法被稱作動態路由
:id
會接收任意的內容作為一個參數傳入。例如我們進入 /admin/edit/banana
頁面
那麼就可以在 Edit.vue
這個組件上使用
{{$route.params.id}}
來呼叫到 :id
接收到的值,在上面的例子中就是「banana」
New.vue
<template>
<div>
<div class="title">
<h1>This is Admin/New</h1>
</div>
</div>
</template>
Products.vue
<template>
<div>
<div class="title">
<h1>This is Admin</h1>
</div>
</div>
</template>
建立完成之後就完成了嵌套路由的應用
專案範例程式碼 GitHub 網址:ray247k/mini-E-commerce