嵌套路由是指在一個 router-view
裏包 router-view
,像是在一個畫框裏,再加上一個畫框。例如 /products/tshirt
與 /products/shoes
,做法可以是在 Product.vue 此頁面元件裏再加一個 router-view
,用來切換顯示 Tshirt 與 Shoes 元件。
至於嵌套命名視圖,其實是結合「嵌套路由」和「命名視圖」這兩個概念。前者就是以上提到的意思。後者就是指,當一個畫面要同時顯示多於一 router-view
時,就必須要使用命名視圖(named view)。
結合兩者概念的話,就是指在一個 router-view
裏包 router-view
,並在內層的 router-view
裏,再包多於一個的 router-view
(需使用命名視圖)。
雖然這題不是常見面試題,但實作時這兩個概念出現的機會挺高。而且作為新手,自己也曾試過搞混了兩者的意思,因此想寫一篇文章來整理概念。
嵌套路由較易理解,先看看官方解說圖:
截圖自官方文件
簡單說,就是在一個元件裏放一個 router-view
,在這裏可以切換顯示不同的元件。以上例子就是切換 Profile 與 Posts。
為什麼叫嵌套?因為如果你使用 Vue CLI,別忘了最頂層預設已經放了一個 router-view
。示範一下,你剛建立 Vue CLI 專案時,會有以下預設程式碼:
App.vue
<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view/>
</template>
你可以把 nav
刪除,這樣看就更清晰:
<template>
<router-view/>
</template>
預設路由設定是:
router/ index.js
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
}
]
用 Vue 檢查工具看,一目了然:
所以,初始化時,最頂層一定會有一個 router-view
,不然沒法顯示元件。這個 router-view
的作用就像一個畫框一樣,你可以隨時切換顯示不同元件,也就是 SPA 的概念:
回到重點,如果在元件裏,再加一個 router-view
,並可以切換顯示不同元件,這就是嵌套路由的意思了。白話講,就是在一個畫框裏的元件上,再放一個畫框,切換顯示不同元件。
以 /about
頁面為例,在 about 頁面加上一個 router-view
,切換顯示 Skills
、Greeting
、Contact
這三個元件。
About.vue
<template>
<div class="about">
<h1>This is an about page</h1>
<router-link to="/about/greeting"> Greeting</router-link>
<router-link to="/about/skills"> Skills </router-link>
<router-link to="/about/contact"> Contact </router-link>
<router-view></router-view>
</div>
</template>
使用 children
設定嵌套路由:
router/ index.js
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
children: [
{
path: 'skills',
component: Skills
},
{
path: 'greeting',
component: Greeting
},
{
path: 'contact',
component: Contact
}
]
}
]
然後各自建立 Skills.vue、Greeting.vue、Contact.vue 的檔案,這裏就不示範了。目前 About 裏的的概念如下:
結果就是在 About 元件裏的 Router view 內,可以不斷切換元件:
注意,當你進入 /about
頁面,結果會是空的,因為目前是路由是 /about
,並不是 /about/skills
、/about/greeting
或者 /about/contact
。如果想預設顯示某個嵌套路由的元件,舉例說是 Skills,就要把 path 設定為 ''
。
router/ index.js
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
children: [
{
path: '',
component: Skills
},
...
]
}
結果訪問 /about
時,就會渲染 Skill 元件。
了解過嵌套路由,就很快會理解嵌套命名視圖。在這之前,要先知道什麼是命名視圖。當一個畫面裏,我們想設置多於一個 router-view
時,其他 router-view
就需要具名,不然 Vue 不知道這些視圖要放什麼元件。因此,命名視圖就是當畫面上有多於一個 router-view
時,所需要的元素。
以後台 dashboard 為例,在同一個畫面裏,左邊 Sidebar,右邊有 Banner 和 Content。我們在同一個畫面放置 3 個 router-view,其中一個可以不用命名,即是預設 router-view,其餘兩個就要命名。
以上例子就是在 App.vue 放置 3 個 router-view,以下先省略 CSS 部分。
<template>
<router-view name="Sidebar" />
<router-view name="Banner" />
<router-view/>
</template>
router/ index.js
const routes = [
{
path: '/',
components: {
default: Content,
Banner,
Sidebar
}
}
]
嵌套命名視圖就是結合以上提到「嵌套路由」、「命名視圖」的概念。再以後台 dashboard 作例子。
假設現在有首頁、產品頁。在產品頁裏,有分 T-shirt 和 Shoes 產品。在 T-shirt 頁裏,用 2 個 router-view
顯示男女裝 T-shirt。而在 Shoes 頁裏,也用 2 個 router-view
顯示 Sneakers 和 Boots。
所以,Product 頁的結構如下:
products/tshirt
及 products/shoes
。詳細程式碼最後才分享,以下先看重點部分。
最外層 App.vue,放置 router-link 以及 router-view,讓使用者切換瀏覽主頁以及產品頁:
<template>
<router-link to="/"> Homepage </router-link>
<router-link to="/products"> Products </router-link>
<router-view />
</template>
點擊 Products 後,進入 Products 頁:
Products.vue
<template>
<div class="page">
<Sidebar />
<div class="content">
<!-- 當切換到 "/products/tshirt",以下才會顯示-->
<router-view />
<router-view name="MenTshirt" />
<!-- 當切換到 "/products/shoes",以下才會顯示-->
<router-view name="Sneakers" />
<router-view name="Boots" />
</div>
</div>
</template>
以上畫面中間內容是空,因為現在是在 /products
,不是 /products/tshirt
或者 /products/shoes
,所以不會顯示這裏的 router-view。當按下 Nav 的按鈕,就能切換顯示相應的 router-view。
看看核心部分 router / index.js
const routes = [
{
path: "/",
component: Home
},
{
path: "/products",
component: Products,
children: [
{
path: "tshirt",
components: {
default: WomenTshirt,
MenTshirt
}
},
{
path: "shoes",
components: {
Sneakers,
Boots
}
}
]
}
];
以上可見,當切換到 /products/tshirt
時,才會顯示 WomenTshirt 和 MenTshirt。/products/shoes
則會顯示 Sneakers 和 Boots。
https://codesandbox.io/s/qian-tao-ming-ming-shi-tu-6cbmo?file=/src/App.vue:0-142
router-view
裏,再包一個 router-view
。router-view
,就需要用命名視圖。