设置 Vue 路由器以供 Vue 使用

当我们将 Vue Router 添加到项目中时,Vue CLI 会创建一个 router 文件夹并将其添加到代码目录中,其中包含一个自动生成的 index.js 文件。 该文件包含我们的路由器的必要配置。

我们将导航到该文件并完成 Vue Router 的基本预定义配置。

首先,您会注意到我们需要分别从 vue 和 vue-router 包导入 Vue 和 VueRouter。 然后我们调用 Vue.use (VueRouter) 将其安装为插件以在我们的应用程序中使用:

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

Vue.use 是一个全局方法,如第 5 章 “全局组件组合” 中所述。 一旦 Vue 可用作应用程序的全局变量,它就会触发 VueRouter 的内部 install 方法以及 Vue 构造函数。 此方法有一个内置机制来防止多次安装插件。

执行 Vue.use(VueRouter) 后,以下对象可在任何组件中访问:

  • this.$router – 全局路由器对象

  • this.$route – 当前路由对象

this 指向上下文中的组件。现在我们已经在应用程序中注册了 Vue Router 的使用,让我们继续下一步 - 为路由器实例的配置对象定义路由。

定义 Routes

在 Web 应用程序中,路由(route)是 URL 路径模式,并映射到特定的处理程序(handler)。在现代 Web 开发中,处理程序(handler)是一个组件,定义并位于物理文件中。例如,当用户输入路由 localhost:8080//home 时,如果 Home 映射到此特定路由,则路由系统知道触发处理程序 Home 相应地渲染内容。

如前面的示例所示,在应用程序内设置导航路由(或路径)至关重要。

每个路由都是一个对象字面值,其属性由 RouteConfig 接口声明:

interface RouteConfig = {
    path: string,
    component?: Component,
    name?: string, // for named routes
    components?: { [name: string]: Component }, // for named views
    redirect?: string | Location | Function,
    props?: boolean | Object | Function,
    alias?: string | Array<string>,
    children?: Array<RouteConfig>, // for nested routes
    beforeEnter?: (to: Route, from: Route, next: Function) => void,
    meta?: any,
    // 2.6.0+
    caseSensitive?: boolean, // use case sensitive match? (default: false)
    pathToRegexpOptions?: Object // path-to-regexp options for compiling regex
}

应用程序所需的所有路由都位于 routes 的 Array 实例中:

const routes = [
    //Route1,
    //Route2,
    //...
]

现在,让我们回到之前的文件,取消注释路由(routes)内的代码。为了方便起见,将有两个预定义的路由,homeabout,每个路由作为一个对象并位于 paths 数组中。

让我们仔细看看第一条路由作为例子:

{
    path: '/',
    name: 'home',
    component: Home
}

path 属性是必需(required)的字符串,指示目标路由的路径,并解析为浏览器导航的绝对 URL 路径。例如,/about 路径将被转换为 <app domain>/about(localhost:8080/about 或 example.com/about)。

在这种情况下,当正斜杠 / 后面没有其它指示符时,例如当用户导航到 <app-domain> 或 <app-domain>/ 时,Vue Router 将 / – 空路径 – 作为加载应用程序的默认路径。

下一个属性是 name,它是一个字符串,表示为目标路由指定的名称。尽管它是可选的,但强烈建议为每个路由定义一个名称,以实现更好的代码维护和路由跟踪目的,我们将在本章后面的 “传递路由参数” 部分进一步讨论这一点。

最后一个属性是 Component,它是一个 Vue 组件实例。 router-view 使用此属性作为对视图组件的引用,以在路径处于活动状态时渲染页面内容。

在这里,我们将路由定义为 home 路由,映射为应用程序的默认路径,并与 Home 组件的内容绑定。

Vue CLI 还为这两个示例路由自动生成两个简单的组件 - Home 和 About。

在下一节中,我们将介绍一些在加载要与路由一起使用的组件时有用的提示。

加载路由配置组件的技巧

当然,我们需要导入组件以将其绑定到同一 index.js 文件中的目标路由。经典且最流行的方法是在文件顶部导入,如下所示:

import Home from '../views/Home.vue'

通常这会被添加到主要导入下,如图 6.5 所示:

image 2023 10 14 10 17 44 579
Figure 1. Figure 6.5: Import Home component on line 3 – src/router/index.js

然而,更有效的方法是延迟加载组件。延迟加载也称为按需加载,是一种旨在在运行时优化网站或 Web 应用程序内容的技术。它有助于减少首次加载时下载应用程序所需的时间消耗和资源量。这种优化对于确保尽可能最佳的用户体验至关重要,因为每一毫秒的等待都很重要。除此之外,延迟加载还可以在路由级别实现更好的代码分割,以及大型或复杂应用程序中的性能优化。

我们可以利用 webpack 延迟加载组件。我们可以在定义 about 路由的名称后动态添加以下内容,而不是像我们对 Home 所做的那样在文件顶部导入 About 组件(参见图 6.5):

component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')

在这里,我们动态延迟加载 about 路由的 About 视图组件。在编译过程中,webpack 会为 about 路由生成一个具有指定名称(“about”)的单独块,并且仅在用户访问该路由时加载它。

在大多数情况下,由于用户可能会在第一次访问时到达默认路径,因此最好不要延迟加载默认组件(我们应用程序中的 Home),而是以正常方式导入它。因此,这里的技巧是在设计路由时确定哪些组件应该延迟加载,并结合这两种方法以获得最大的好处。

我们现在将了解如何设置路由器实例。

设置路由器实例

定义路由后,最后一步是根据给定的配置选项创建路由器(router)实例:

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

配置是一个由不同属性组成的对象,有助于形成应用程序的路由器。我们现在将在以下小节中检查这些属性。

routes

路由(routes)是传递给构造函数的必备选项。否则,路由器将无法识别路径并相应地将用户引导至合适的视图内容。

mode

mode 决定路由器的模式。VueRouter 中的 URL 有两种模式:

  • 历史(history)模式:这通过 HTML5 历史 API 来利用默认的 history.pushState() API。它使我们能够在不重新加载页面的情况下实现 URL 导航,并使 URL 路径易于阅读,例如 yourapplication.com/about。

  • 散列(hash)模式:此模式使用散列符号(#) 来模拟 URL,例如,yourapplication.com/#about 表示 “关于” 页面,或 youapplication/#/ 表示应用程序的主页 URL。

base

base 确定应用程序的基本 URL。它将被设置为 process.env.BASE_URL,以允许开发人员从应用程序代码外部(例如,从 .env 文件)控制它。 因此,开发人员可以设置运行时应提供代码的目录。

现在 base 配置完成了,我们已经创建了路由器(router)实例。剩下的就是导出它:

export default router

然后在创建主应用程序实例的 new Vue 对象之前将其导入 main.js 中。我们仍然需要在实例配置中指定 router,如下所示:

import router from './router'

Vue.config.productionTip = false

new Vue({
    router, //specify the router configuration for use
    render: h => h(App)
}).$mount('#app')

使用此更新的代码,我们的应用程序现在将渲染如下:

image 2023 10 14 10 30 36 689
Figure 2. Figure 6.6: Home page of the Hello Vue Router application in the browser

如果我们导航到 localhost:8080/about,我们将从自动生成的代码中看到 about 组件的渲染内容:

<template>
    <div class="about">
        <h1>This is an about page</h1>
    </div>
</template>

该网站应类似于图 6.7 所示:

image 2023 10 14 10 32 34 109
Figure 3. Figure 6.7: About page of the "Hello Vue Router" application in the browser

在本节中,我们研究了如何使用延迟加载组件来加速大型且复杂的 SPA。我们还研究了设置路由器时可以设置的一些选项,例如路由(routes)、模式(mode)和基础(base)。在下一节中,我们将学习如何借助 Vue Router 实现和添加消息提要页面。

练习 6.01:使用 Vue Router 实现和添加消息源页面

我们将创建一个新页面,向用户显示消息列表。 用户只要在浏览器中输入 localhost:8080/messages 路径就可以访问此页面。

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

  1. 使用 vue create 生成的应用程序作为起点,或使用 vue-cli 创建一个新应用程序。确保在生成项目时启用了路由器,如本章前面所述:

    vue create Exercise6.01
  2. 让我们通过将 MessageFeed.vue 文件添加到 ./src/views/ 文件夹来创建一个名为 MessageFeed 的新视图组件:

    image 2023 10 14 10 38 20 907
    Figure 4. Figure 6.8: The views directory hierarchy

    该组件将渲染消息列表。我们的消息列表被定义为组件 data 属性中称为消息(messages)的字符串数组,如下所示:

    <template>
        <div>
            <h2> Message Feed </h2>
            <p v-for="(m, i) in messages" :key="i">
                {{ m }}
            </p>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                messages: [
                    'Hello, how are you?',
                    'The weather is nice',
                    'This is message feed',
                    'And I am the fourth message'
                ]
            }
        }
    }
    </script>
  3. 在 src/router/index.js 创建一个路由器文件。它应该导入 VueRouter 并告诉 Vue 使用路由器(router),如下所示:

    import Vue from 'vue'
    import VueRouter from 'vue-router'
    import Home from '../views/Home.vue'
    
    Vue.use(VueRouter)
  4. 接下来,在 ./src/router/index.js 中,我们声明一个为 MessageFeed 指定的路由,名为 messageFeed,并将其路径设置为 /messages。我们还将延迟加载该组件。通过将具有所需信息的对象附加到路由(routes)数组来完成此步骤:

    export const routes = [
        {
            path: '/',
            name: 'home',
            component: Home
        },
        {
            path: '/about',
            name: 'about',
            // route level code-splitting
            // this generates a separate chunk (about.[hash].js) for this route
            // which is lazy-loaded when the route is visited.
            component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
        },
        {
            path: '/messages',
            name: 'messageFeed',
            component: () => import(/* webpackChunkName: "messages" */ '../views/MessageFeed.vue')
        }
    ]
  5. 最后,在同一个文件中,使用我们定义的路由(routes)创建一个路由器(router)实例:

    const router = new VueRouter({
        mode: 'history',
        base: process.env.BASE_URL,
        routes
    })
    
    export default router
  6. 使用以下命令运行应用程序:

    yarn serve
  7. 在浏览器中访问 localhost:8080/messages 后,页面应该显示正确的内容 - Message Feed 页面,如以下屏幕截图所示:

    image 2023 10 14 10 53 11 447
    Figure 5. Figure 6.9: Message feed page rendered by the application

这演示了使用 Vue Router 将新页面路由添加到 Vue.js 应用程序是多么简单,同时保持代码井井有条且易于阅读。现在我们已经准备好使用路由,我们可以为用户提供在页面之间导航的能力,而无需输入完整路径。

设置导航链接

如果 router-view 负责渲染相对于 URL 路径的正确活动视图内容,则 router-link 是一个 Vue 组件,可帮助用户在启用了路由的应用程序内导航。 默认情况下,它会渲染一个锚标记 <a> 以及由其 to 属性生成的正确 href 链接。

在我们由 Vue CLI 生成的示例应用程序中,由于预先填充了两条路由,因此在 <router-view/> 之前的 App.vue 的 <template> 部分中还添加了两个 router-link 实例:

<div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
</div>

由于我们在历史(history)模式下使用 base 选项,因此每个 router-link 的 to 属性应该接收与目标路由对象中声明的 path 属性相同的值。

此外,因为我们的路由(route)是命名的,所以 to 属性的另一种替代方法是具有与名称相同的值,而不是路径。强烈建议使用该名称,以避免复杂的链接重构,以防我们必须调整应用程序中某些路由的路径。因此,我们可以重写我们的链接如下:

<div id="nav">
    <router-link to="home">Home</router-link> |
    <router-link to="about">About</router-link> |
</div>

我们还可以选择将位置描述符对象绑定到 to 属性,其格式与路由对象类似。考虑以下示例:

<router-link :to="{path: '/'}">Home</router-link>

此外,当相关路由处于活动状态时,一个额外的 CSS 类 router-link-active 将被添加到 <a> 标签中。这个类可以通过 router-link 组件的 active-class 属性来定制。

在 DevTools 中,我们可以看到 router-link 组件的渲染如下:

image 2023 10 14 11 05 11 610
Figure 6. Figure 6.10: router-link in the browser’s DevTools

浏览器中的视图将如下所示:

image 2023 10 14 11 05 51 048
Figure 7. Figure 6.11: Home page of Hello Vue Router app with navigation links

请注意,由于我们可以在组件内访问 this.$router,因此我们可以使用 this.$router.push() 以编程方式触发导航路由,并以与使用类似的方式传递路径或路由器对象:

this.$router.push('/home')

在本节中,我们创建了一个示例页面,该页面在 /messages 路由位置渲染消息列表。我们还研究了如何使用 <router-link/> 元素以类似于传统 HTML <a> 标记的方式在视图之间导航。

接下来,我们将了解如何以类似于 Web 浏览器的后退按钮的方式以编程方式将用户发送到他们上次查看的路由。

实现后退按钮的提示

有时我们想导航回到上一页。 使用 this.$router.push() 可以实现这一点,但这会在历史堆栈中添加更多路由,而不是返回。 正确的技术是使用 this.$router.go(steps),其中 steps 是一个整数,表示历史堆栈中后退/前进的步数。此功能的工作原理与 window.history.go(steps) 类似。

考虑以下示例:

this.$router.go(-1) // similar to window.history.back() - go back one page

除此之外,您还可以使用相同的方法向前导航到之前加载过且仍然存在于历史堆栈中的页面,如下所示:

this.$router.go(1) // similar to window.history.forward() – go forward one page

在本节中,我们研究了如何手动访问路由器的历史记录,以便将用户发送到他们之前所在的页面。

在下一节中,我们将利用导航链接将新的消息源页面添加到应用程序的导航菜单中。

练习 6.02:将导航链接添加到 MessageFeed 路由

我们将添加一个快速链接到我们在 Exercise 6.01 使用 Vue Router 实现和添加消息源页面中创建的 MessageFeed 路由,使用 to 属性和 router-link,如上一主题中所述。

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

  1. 使用 Vue 生成的入门应用程序作为起点,或使用 Vue cli 创建一个新应用程序。 确保在生成项目时启用了路由器,如本章前面所述:

    vue create Exercise6.02
  2. 在 ./src/App.vue 文件中,除了自动生成的 home 和 about 的 router-link 组件之外,还添加另一个指向 Message Feed 标题下的 /messages 路径的 router-link 组件:

    <template>
        <div id="app">
            <div id="nav">
                <router-link to="/">Home</router-link> |
                <router-link to="/about">About</router-link> |
                <router-link to="/messages">Message Feed</router-link>
            </div>
            <router-view/>
        </div>
    </template>

    我们将在任何视图中看到可用的导航链接,并且当用户离开时它们不会消失,因为它们不是路由器视图组件的一部分。我们的屏幕应如下所示:

    image 2023 10 14 11 33 15 328
    Figure 8. Figure 6.12. Home page of the Hello Vue Router app with updated navigation links
  3. 让我们将 to 值更改为指向名为 messageFeed 的对象,该对象与 ./src/App.vue 中为此路由给出的 name 相同:

    <router-link :to="{ name: `messageFeed` }">Message Feed</router-link>
  4. 导航应该像以前一样工作;单击消息源链接应将您定向到 /messages,如以下屏幕截图所示:

    image 2023 10 14 11 35 14 680
    Figure 9. Figure 6.13: Message Feed page of Hello Vue Router after clicking on the Message Feed link
  5. 现在,打开位于 ./src/router/ 文件夹中的 index.js 文件,并将为 messageFeed 路由定义的路径从 /messages/ 更改为 /messagesFeed:

    export const routes = [
        {
            path: '/',
            name: 'home',
            component: Home
        },
        {
            path: '/about',
            name: 'about',
            // route level code-splitting
            // this generates a separate chunk (about.[hash].js) for this route
            // which is lazy-loaded when the route is visited.
            component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
        },
        {
            path: '/messagesFeed',
            name: 'messageFeed',
            component: () => import(/* webpackChunkName: "messageFeed" */
            '../views/MessageFeed.vue')
        }
    ]
  6. 使用以下命令运行应用程序:

    yarn serve

导航到应用程序的主页,然后再次单击 Message Feed。它应该显示与以前相同的消息源页面,但请注意 URL 路径更改为 /messagesFeed:

image 2023 10 14 14 21 48 311
Figure 10. Figure 6.14: Message Feed page rendered with the updated URL path

请注意,仅用一行代码即可轻松设置指向 /messages 路径的链接,并且无需重构即可更新相关路径。到目前为止,我们刚刚定义了一些简单的路由,没有为目标路由添加任何额外参数。这将是我们的下一个挑战。