VUE router-view 頁面布局 (嵌套路由+命名視圖)
嵌套路由
實際生活中的應用界面,通常由多層嵌套的組件組合而成。同樣地,URL 中各段動態路徑也按某種結構對應嵌套的各層組件,例如:
/user/foo/profile /user/foo/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile | | +------------> | | Posts | | | | | | | | | | | +--------------+ | | +-------------+ | +------------------+ +-----------------+
借助 vue-router
,使用嵌套路由配置,就可以很簡單地表達這種關系。
接著上節創建的 app:
<div id="app">
<router-view></router-view>
</div>
const User = {
template: ‘<div>User {{ $route.params.id }}</div>‘
}
const router = new VueRouter({
routes: [
{ path: ‘/user/:id‘, component: User }
]
})
這裏的 <router-view>
是最頂層的出口,渲染最高級路由匹配到的組件。同樣地,一個被渲染組件同樣可以包含自己的嵌套 <router-view>
。例如,在 User
組件的模板添加一個 <router-view>
:
const User = {
template: `
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view></router-view>
</div>
`
}
要在嵌套的出口中渲染組件,需要在 VueRouter
的參數中使用 children
配置:
const router = new VueRouter({
routes: [
{ path: ‘/user/:id‘, component: User,
children: [
{
// 當 /user/:id/profile 匹配成功,
// UserProfile 會被渲染在 User 的 <router-view> 中
path: ‘profile‘,
component: UserProfile
},
{
// 當 /user/:id/posts 匹配成功
// UserPosts 會被渲染在 User 的 <router-view> 中
path: ‘posts‘,
component: UserPosts
}
]
}
]
})
要註意,以 /
開頭的嵌套路徑會被當作根路徑。 這讓你充分的使用嵌套組件而無須設置嵌套的路徑。
你會發現,children
配置就是像 routes
配置一樣的路由配置數組,所以呢,你可以嵌套多層路由。
此時,基於上面的配置,當你訪問 /user/foo
時,User
的出口是不會渲染任何東西,這是因為沒有匹配到合適的子路由。如果你想要渲染點什麽,可以提供一個 空的 子路由:
const router = new VueRouter({
routes: [
{
path: ‘/user/:id‘, component: User,
children: [
// 當 /user/:id 匹配成功,
// UserHome 會被渲染在 User 的 <router-view> 中
{ path: ‘‘, component: UserHome },
// ...其他子路由
]
}
]
})
命名視圖
有時候想同時 (同級) 展示多個視圖,而不是嵌套展示,例如創建一個布局,有 sidebar
(側導航) 和 main
(主內容) 兩個視圖,這個時候命名視圖就派上用場了。你可以在界面中擁有多個單獨命名的視圖,而不是只有一個單獨的出口。如果 router-view
沒有設置名字,那麽默認為 default
。
<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>
一個視圖使用一個組件渲染,因此對於同個路由,多個視圖就需要多個組件。確保正確使用 components
配置 (帶上 s):
const router = new VueRouter({
routes: [
{
path: ‘/‘,
components: {
default: Foo,
a: Bar,
b: Baz
}
}
]
})
以上案例相關的可運行代碼請移步這裏。
#嵌套命名視圖
我們也有可能使用命名視圖創建嵌套視圖的復雜布局。這時你也需要命名用到的嵌套 router-view
組件。我們以一個設置面板為例:
/settings/emails /settings/profile
+-----------------------------------+ +------------------------------+
| UserSettings | | UserSettings |
| +-----+-------------------------+ | | +-----+--------------------+ |
| | Nav | UserEmailsSubscriptions | | +------------> | | Nav | UserProfile | |
| | +-------------------------+ | | | +--------------------+ |
| | | | | | | | UserProfilePreview | |
| +-----+-------------------------+ | | +-----+--------------------+ |
+-----------------------------------+ +------------------------------+
Nav
只是一個常規組件。UserSettings
是一個視圖組件。UserEmailsSubscriptions
、UserProfile
、UserProfilePreview
是嵌套的視圖組件。
註意:我們先忘記 HTML/CSS 具體的布局的樣子,只專註在用到的組件上
UserSettings
組件的 <template>
部分應該是類似下面的這段代碼:
<!-- UserSettings.vue -->
<div>
<h1>User Settings</h1>
<NavBar/>
<router-view/>
<router-view name="helper"/>
</div>
嵌套的視圖組件在此已經被忽略了,但是你可以在這裏找到完整的源代碼
然後你可以用這個路由配置完成該布局:
{
path: ‘/settings‘,
// 你也可以在頂級路由就配置命名視圖
component: UserSettings,
children: [{
path: ‘emails‘,
component: UserEmailsSubscriptions
}, {
path: ‘profile‘,
components: {
default: UserProfile,
helper: UserProfilePreview
}
}]
}
一個可以工作的示例的 demo 在這裏。
https://jsfiddle.net/22wgksa3/8174/
//**********************************html************************
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<div id="app">
<h1>Nested Named Views</h1>
<router-view></router-view>
</div>
//*****************************js*********************
const UserSettings = {
template: `
<div class="us">
<h2>User Settings start</h2>
<router-view ></router-view>
<router-view name="a"></router-view>
<router-view name="b"></router-view>
</br>
<h2>User Settings End</h2>
</div>
`
}
const Foo = { template: ‘<h2>pagecontent</h2>‘ }
const Bar = { template: ‘<h2>sidebar</h2>‘ }
const Baz = { template: ‘<h2>navbar</h2>‘ }
const router = new VueRouter({
mode: ‘history‘,
routes: [
{ path: ‘/‘,
// You could also have named views at tho top
component: UserSettings,
children: [
{
path: ‘‘,
components: {
default: Baz,
a: Bar,
b: Foo
}
}
]
}
]
})
new Vue({
router,
el: ‘#app‘
})
//****************************************效果如下*********************
Nested Named Views
- /
User Settings start
navbar
sidebar
pagecontent
User Settings End
VUE router-view 頁面布局 (嵌套路由+命名視圖)