使用布局

在 Vue.js 应用程序中实现布局的方法有很多。其中之一是使用插槽(slot)并在 router-view 之上创建静态包装布局组件。尽管具有灵活性,但这种方法会导致沉重的性能成本,既会不必要地重新创建组件,又会导致每次路由更改时都需要额外的数据获取。

在本节中,我们将讨论一种更好的方法,即利用动态组件的强大功能。其组成部分如下:

<component :is="layout"/>

在 App.vue 文件中,我们将 Vue CLI 生成的默认视图更改为仅 <router-view> 及包围它的包装器。该包装器是一个动态组件,它将渲染布局(layout)变量中定义的任何组件:

<template>
    <div id="app">
        <component :is="layout">
            <router-view/>
        </component>
    </div>
</template>

默认情况下,我们将 data 中的布局(layout)定义为 default.vue 布局:

<script>
export default {
    data() {
        return {
            layout: () => import(/* webpackChunkName: "defaultlayout" */'./layouts/default.vue')
        }
    }
}
</script>

在 layouts 文件夹中,我们将创建默认(default)布局组件,其中包含简单的标题导航、渲染实际内容的 main 插槽(即 <router-view> 渲染的内容)和页脚:

<template>
    <div class="default">
        <nav>
            <router-link to="/">Home</router-link> |
            <router-link to="/about">About</router-link>
        </nav>
        <main class="main">
            <slot/>
        </main>
        <footer>
            <div>Vue Workshop Chapter 06</div>
        </footer>
    </div>
</template>

回到我们的 App.vue 文件,为了使布局组件(component)渲染响应相应的路由变化,router-view 应该控制渲染哪个布局。换句话说,布局应该是可更新的,并由在 router-view 内渲染的视图组件决定。为了实现这一点,我们将使用 <router-view> 上的 sync 将 currentLayout 属性定义为与布局(layout)同步:

<component :is="layout">
    <router-view :currentLayout="layout"/>
</component>

创建 Home.vue 组件的实例后,我们将发出一个 update:currentLayout 事件,其中包含要相应更新和渲染的所需布局:

import DefaultLayout from '../layouts/default.vue';

export default {
    name: 'home',
    components: {
        HelloWorld,
    },
    created() {
        this.$emit('update:currentLayout', DefaultLayout)
    }
}

输出如下:

image 2023 10 15 09 05 45 088
Figure 1. Figure 6.42: Home page rendered with a layout

由于布局(layout)组件不是 router-view 组件的一部分,因此只要布局在视图内发生变化,它就会重新渲染。这将在用户导航期间保持应用程序的性能。

在本节中,我们研究了如何使用动态组件组件为不同的路由提供不同的布局。这使我们能够拥有不同的通用布局,例如,一个用于面向用户的页面的全局菜单和另一个用于管理页面的全局菜单,根据所使用的路由进行渲染。 在下一节中,我们将基于在这里学到的知识,创建具有动态嵌套路由和布局的消息应用程序。

活动 6.01:使用动态、嵌套路由和布局创建消息 SPA

此活动旨在利用您对 Vue Router 有关注册路由和处理动态路由、嵌套路由和路由 Hook 的知识来创建消息 SPA。 该应用程序将允许用户撰写新消息、查看消息源以及在消息之间导航以查看其详细信息:

  1. 创建一个 MessageEditor 视图(位于 src/views/MessageEditor.vue),它将向用户渲染一个带有文本区域(textarea)的视图和一个用于保存消息的提交(submit)按钮。

  2. 在 src/router/index.js 中将编辑器路由注册为 MessageEditor 作为其视图。

  3. 创建一个 MessageList 视图(位于 src/views/MessageList.vue),该视图将渲染由 a 标签包装的消息 id 值列表,该标签将在选择时定向到具有给定 id 的单个消息页面。

  4. 在 src/router/index.js 中将 MessageList 注册为列表路由作为其视图。

  5. 添加消息视图(位于 src/views/Messages.vue),它将渲染到编辑器或列表的链接作为其嵌套路由,并相应地渲染嵌套视图。

  6. 当用户离开编辑器(editor)时,如果某些内容尚未提交,则会显示一条消息,询问他们是否要在离开之前保存。“是”将继续,“否”将中止导航。

  7. 添加一个消息视图(位于 src/views/Message.vue),它将渲染来自 props 的消息内容,并有一个后退(back)按钮用于返回到上一个视图。默认情况下,它应该转到消息。

  8. 使用 src/router/index.js 中的 message/:id 动态路由注册 Message 视图。

  9. 通过创建两种不同的简单布局来改进 UI,一种用于消息(messages)(仅包含标题),另一种用于消息(messages)(包含标题(title)和后退(back)按钮)。

预期输出如下:

  • 显示消息源的 /list 视图应如下所示:

    image 2023 10 15 09 29 59 516
    Figure 2. Figure 6.43: The /list view in the Messages app
  • 允许用户撰写和发送新消息的 /editor 视图如下所示:

    image 2023 10 15 09 30 46 726
    Figure 3. Figure 6.44: The /editor view in the Messages app
  • 消息应用程序中的 /message/:id 动态路由(此处,/message/0 表示 id 为 0 的消息)如下所示:

    image 2023 10 15 09 31 34 476
    Figure 4. Figure 6.45: The /message/0 view in the Message app

当用户尝试使用未保存的消息导航离开时,将显示一条警报,如以下屏幕截图所示:

image 2023 10 15 09 32 24 006
Figure 5. Figure 6.46: The /editor view when the user tries to navigate away with an unsaved message

总结

在本章中,我们了解了 Vue Router 提供的最基本、最有用的功能,用于以有效且有组织的方式为任何 Vue.js 应用程序构建路由。

router-view 和 router-link 允许应用程序开发人员轻松设置相关视图的导航路径并维护 SPA 概念。 事实上,它们本身就是 Vue 组件,为我们作为开发人员提供了 Vue 架构的好处,使我们能够灵活地实现嵌套视图或布局。

将路由定义为具有不同属性的对象可以简化架构过程,包括重构现有路径以及向系统添加新路由。 使用路由器参数和模式提供具有可重用视图的动态路由,并允许页面之间的通信和数据保存。

最后,通过 Hooks,我们看到了如何拦截导航流、在需要时设置身份验证、重定向到所需路径,甚至在用户登陆目标页面之前加载和保留一些重要数据。 这些 Hook 在无数的用例中都非常有用,例如在实现后退按钮时。

有了这些,我们现在能够编写一个带有适当导航系统的 Vue.js 应用程序,供用户探索,同时维护每个导航用例(动态路由和嵌套视图)中的数据流和应用程序设计布局。

在下一章中,您将探索如何将过渡应用于路由和不同的动画,以便为您的 Vue 组件和应用程序提供漂亮的加载效果。