通过路由配置来控制视图的选择性渲染
比如要实现两个页面,其两个页面的布局基本相似,唯一不同的是侧边栏的结构和数据不同,此时可以将公共部分抽离出来,对于不同的部分通过路由配置传参来控制到底显示那一部分的内容。
示例
布局1:default-a.vue
布局2:default-b.vue
第一个模块的布局分为三部分,Header
、aside-bar-a
、main
;
第二个模块的布局也是分为三部分:Header
、aside-bar-b
、main
;
这两个模块的布局唯一不同的地方就是aside-bar-a
、aside-bar-b
这两个区域。
当然常规的做法就是针对这两种布局分别创建default-a.vue
和default-b.vue
,第一个模块的布局采用default-a.vue
的布局,第二个模块的布局采用default-b.vue
的布局。如此以来就会出现代码冗余的情况:两个模块的布局除去侧边栏布局外,其他部分完全相同。
所以才引入路由视图的概念:
命名视图
有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 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 组件的 部分应该是类似下面的这段代码:
<!-- UserSettings.vue -->
<div>
<h1>User Settings</h1>
<NavBar/>
<router-view/>
<router-view name="helper"/>
</div>
然后你可以用这个路由配置完成该布局:
{
path: '/settings',
component: UserSteeings,
children: [
{
path: 'emails',
component: UserEmailsSubscriptions
}, {
path: 'profile',
components: {
default: UserProfile,
helper: UserProfilePreview
}
}
]
}
实例
常规做法
L layouts
L aside-bar-a.vue
L aside-bar-b.vue
L default-a.vue
L default-b.vue
<!-- default-a.vue -->
<template>
<div>
<i-header></i-header>
<el-container>
<aside-bar-a></aside-bar-a>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>
<!-- default-b.vue -->
<template>
<div>
<i-header></i-header>
<el-container>
<aside-bar-b></aside-bar-b>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>
import LayoutA from '../layout/default-a.vue'
import LayoutB from '../layout/default-b.vue'
const router = new VueRouter({
routes: [
{
path: '/main-home',
component: LayoutA,
children: [...]
}, {
path: '/other-home',
component: LayoutB,
children: [...]
}
]
})
模块整合
L layouts
L aside-bar-a.vue
L aside-bar-b.vue
L default.vue
第一种方式:采用视图命名的方式
<!-- default.vue -->
<template>
<div>
<i-header></i-header>
<el-container>
<router-view name="aside-bar-a"></router-view>
<router-view name="aside-bar-b"></router-view>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>
在路由配置文件中引入用于区分的两组件aside-bar-a
和aside-bar-b
,根据命名的视图名称进行分别配置,从而通过访问不同的路由加载不同的视图。
import Layout from '../layout/default.vue'
import AsideBarA from '../layout/aside-bar-a.vue'
import AsideBarB from '../layout/aside-bar-b.vue'
const router = new VueRouter({
routes: [
{
path: '/main-home',
components: {
default: Layout,
'aside-bar-a': AsideBarA
},
children: [...]
}, {
path: '/other-home',
components: {
default: Layout,
'aside-bar-b': AsideBarB
}
children: [...]
}
]
})
第二种方式:采用动态组件加载的方式
在布局default.vue
文件中引入用于区分的两组件aside-bar-a
和aside-bar-b
,用于路由传参来控制组件动态加载
<!-- default.vue -->
<template>
<div>
<i-header></i-header>
<el-container>
<component :is="componentName"></component>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>
<script>
import AsideBarA from './aside-bar-a'
import AsideBarB from './aside-bar-b'
export default {
components: {
AsideBarA,
AsideBarB
},
props: {
componentName: {
type: String,
default: 'aside-bar-a'
}
}
}
</script>
在路由配置文件中,通过设置路由参数来区分需要加载显示的组件。
import Layout from '../layout/default.vue'
const router = new VueRouter({
routes: [
{
path: '/main-home',
component: Layout,
props: {
componentName: 'aside-bar-a'
},
children: [...]
}, {
path: '/other-home',
component: Layout,
props: {
componentName: 'aside-bar-b'
},
children: [...]
}
]
})