嵌套路由

实际上,许多应用程序都是由多个组件组成的,而这些组件又由多个多层嵌套组件组成。 例如,/user/settings/general 表示常规视图嵌套在设置视图中,而此设置(settings)视图嵌套在用户(user)视图中。它代表用户设置页面的一般信息(General information)部分。

大多数时候,我们希望 URL 对应这样的结构,如下图所示:

image 2023 10 15 08 10 37 894
Figure 1. Figure 6.37: User with two nested views – Info and Extra

Vue Router 使用嵌套路由配置和 router-view 组件可以轻松实现这种结构。

让我们回到前面示例中的 User.vue 视图(位于 ./src/views/ 中),并在 <template> 部分添加嵌套的 router-view 组件:

<div>
    <h1>About a user: {{$route.params.id}}</h1>
    <router-link :to="{ name: 'userinfo', params: { id: id }}">Info
    </router-link> |
    <router-link :to="/user/${id}/extra">Extra</router-link>
    <router-view/>
</div>

为了开始将组件渲染到此路由器视图(router-view),我们将配置用户(user)路由以具有 Children 选项,该选项接受子路由的路由配置数组。对于我们的示例,我们将为每个用户添加一个信息(info)和额外(extra)页面。这些子路由将作为 /user/:id/info/user/:id/extra 访问,为每个用户提供唯一的信息(info)和额外(extra)页面:

{
    path: '/user/:id',
    name: 'user',
    component: () => import(/* webpackChunkName: "user" */ '../views/User.vue'),
    props: true,
    children: [{
        path: 'info',
        name: 'userinfo',
        component: () => import(/* webpackChunkName: "info" */ '../views/UserInfo.vue')
    }, {
        path: 'extra',
        component: () => import(/* webpackChunkName: "extra" */ '../views/UserExtra.vue')
    }]
}

并非所有嵌套路径都需要以 / 开头作为其父路径,这将避免它们被视为根路径,并使 Vue Router 更容易计算匹配路由。

当然,我们必须在文件夹中创建两个新视图,以根据收到的 id 渲染有关用户的所有信息:

<template>
<div>
<h2>Name: {{name}}</h2>
<p>Age: {{age}}</p>
</div>
</template>

<script>
import users from '../assets/users.js';

export default {
    data() {
        return {
            name: '',
            age: 0
        }
    },
    beforeRouteEnter(to, from, next) {
        next(vm => {
            const user = users[to.params.id - 1];
            vm.name = user.name;
            vm.age = user.age;
        })
    },
    beforeRouteUpdate(to, from, next) {
        const user = users[to.params.id - 1];
        this.name = user.name;
        this.age = user.age;
        next();
    }
}
</script>

我们还创建 UserExtra.vue,它将渲染额外的信息(如果有的话)。在此示例中,它将仅渲染简单文本:

<template>
    <div>
        <h2>I'm an extra section</h2>
    </div>
</template>

嵌套视图已准备就绪!每当用户单击 Info 链接时,它都会将 UserInfo 视图加载到其中并更新 URL,如下所示:

image 2023 10 15 08 32 12 891
Figure 2. Figure 6.38: User page with nested UserInfo view

当用户单击 Extra 时,他们将看到与以下屏幕截图所示相同的内容:

image 2023 10 15 08 32 47 819
Figure 3. Figure 6.39: User page with nested UserExtra view

在本节中,我们研究了嵌套路由,即具有多个子级的路由。在我们的示例中,子路由是用户信息和用户额外信息。这种模式允许我们创建扩展其父页面的页面。在前面的示例中,我们现在可以编辑 About a user 标头并使其对所有子路由生效。随着项目的增长,利用此模式将使您避免在多个视图中出现重复的代码。

在下一节中,我们将使用迄今为止学到的知识为消息视图组件创建导航选项卡。

练习 6.06:在消息视图中构建导航选项卡

我们将调整从 Nested Routes 部分学到的知识,在 Exercise 6.05 “使用动态路由模式为每条消息实现消息路由” 中的 Message 视图中构建 Navigation 选项卡部分。

要访问本练习的代码文件,请参阅 https://packt.live/2U9Bn6I

  1. 首先,让我们对 src/assets/messages.js 中的消息数据库进行一些更改,添加以下作者(author)和发送(sent)字段:

    const messages = [
        {
            content: 'Hello, how are you?',
            author: 'John',
            sent: '12 May 2019'
        }, {
            content: 'The weather is nice',
            author: 'Lily',
            sent: '12 Jun 2019'
        },
        {
            content: 'This is message feed',
            author: 'Smith',
            sent: '10 Jan 2020'
        },
        {
            content: 'And I am the fourth message',
            author: 'Chuck',
            sent: '1 Apr 2021'
        },
    ];
  2. 接下来,我们将创建一个 MessageAuthor.vue 视图,该视图仅渲染消息创建者的姓名:

    <template>
        <div>
            <h3>Author:</h3>
            <p>{{message.author}}</p>
        </div>
    </template>
    
    <script>
    export default {
        props: {
            message: {
                type: Object,
                default: () => {}
            }
        }
    }
    </script>
  3. 然后我们将创建一个 MessageInfo.vue 视图来渲染 message.sent 值:

    <template>
        <div>
            <h3>Message info: </h3>
            <p>{{message.sent}}</p>
        </div>
    </template>
    
    <script>
    export default {
        props: {
            message: {
                type: Object,
                default: () => {}
            }
        }
    }
    </script>
  4. 完成组件后,我们需要在消息(message)路由的子级下注册新的嵌套路由,位于路由器内的 src/router/index.js 中:

    {
        path: '/message/:id',
        name: 'message',
        component: () => import(/* webpackChunkName: "message" */ '../views/Message.vue'),
        async beforeEnter(to, from, next) { ... },
        props: true,
        children: [{
            path: 'author',
            name: 'messageAuthor',
            props: true,
            component: () => import(/* webpackChunkName: "messageAuthor" */ '../views/MessageAuthor.vue'),
        }, {
            path: 'info',
            props: true,
            name: 'messageInfo',
            component: () => import(/* webpackChunkName: "messageInfo"*/ '../views/MessageInfo.vue'),
        }]
    }
  5. 最后,在 Message.vue 中,我们将代码重构为以下内容:

    <template>
        <div>
            <p>Message content: {{message.content}}</p>
            <router-link :to="{ name: 'messageAuthor', params: { message
            }}">Author</router-link> |
            <router-link :to="{ name: 'messageInfo', params: { message
            }}">Info</router-link>
            <router-view/>
        </div>
    </template>
    
    <script>
    export default {
        props: {
            id: {
                type: String
            },
            message: {
                default: () => {},
                type: Object,
            }
        }
    }
    </script>

    现在我们可以在消息中的 Author 和 Info 选项卡之间导航,如下所示:

    image 2023 10 15 08 53 15 697
    Figure 4. Figure 6.40: Message page with Info selected
  6. 使用以下命令运行应用程序:

    yarn serve

选择 Author 选项时,您将看到以下内容:

image 2023 10 15 08 54 52 050
Figure 5. Figure 6.41: Message page with Author selected

通过这个练习,我们已经涵盖了 Vue Router 的几乎所有基本功能,特别是在处理动态和嵌套路由方面。在最后一节中,我们将介绍如何为应用程序的视图模板创建可重用的布局。