嵌套路由

当项目的页面逐渐变多,结构逐渐变复杂时,只有一层路由是无法满足项目的需要的。比如在某些电商类的项目中,电子类产品划分成页面作为第一层的路由,同时又可以分为手机、平板电脑、电子手表等,这些可以划分成各个子页面,又可以作为一层路由。这时,就需要用嵌套路由来满足这种复杂的关系。

下面先来创建一个一层路由,还是以 User 组件为例,如示例代码7-5-1所示。

<div id="app">
    <router-link to="/user/1">导航page1</router-link>
    <router-link to="/user/2">导航page2</router-link>
    <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>,如示例代码7-5-2所示。

示例代码7-5-2 嵌套路由2
const User = {
    template:
        '<div class="user">'+
        '<h2>User {{ $route.params.id }}</h2>'+
        '<router-view></router-view>'+
        '</div>'
}

然后需要修改配置路由信息 router,新增一个 children 选项来标识出第二层的路由需要有哪些配置,同时新建两个子组件 UserPostsUserProfile,如示例代码7-5-3所示。

<router-link to="/user/1/profile">导航 user 的 profile</router-link>
<router-link to="/user/2/posts">导航 user 的 posts</router-link>
...
const UserProfile = {
    template: '<div>UserProfile</div>'
}

const UserPosts = {
    template: '<div>UserPosts</div>'
}

// 配置路由信息
const router = VueRouter.createRouter({
    history: VueRouter.createWebHashHistory(), // 路由模式
    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 的设置一样,都可以设置由各个组件和路径组成的路由配置对象数组,由此可以推测出,children 中的每一个路由配置对象还可以再设置 children,达到更多层的嵌套。每一层路由的 path 向下叠加共同组成了用于访问该组件的路径,例如 /user/:id/profile 就会匹配 UserProfile 这个组件。

基于上面的设置,当访问 /user/1 时,User 的出口不会渲染任何东西,必须是对应的 /user/:id/profile 或者 /user/:id/posts 才可以。这是因为没有匹配到合适的子路由,如果想要渲染点什么,可以提供一个空的子路由,如示例代码7-5-4所示。

示例代码7-5-4 默认路由
var router = VueRouter.createRouter({
    history: VueRouter.createWebHashHistory(),
    routes: [
        {
            path: '/user/:id',
            component: User,
            children: [
                // 当 /user/:id 匹配成功,UserHome 会被渲染在 User 的 <router-view> 中
                {
                    path: '', component: UserHome
                },
                // 其它子路由
            ]
        }
    ]
})

因为上面的 UserHome 子路由设置的 path 为空,所以会作为导航 /user/1 的匹配路由。