动态路由


动态路由

配置静态路由

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果:

在配置路由时,在需要动态生成的前面加上:

router.js

{
    path: '/user/:userId',
    component: user
}

HTML

这里userId可以直接使用静态数据,如

用户

也可以使用data方法或者computed方法里的动态数据,这时要使用v-bind进行绑定

用户

获取当前路由数据

当前路由数据可以通过$route来获取,该属性包含了当前选中路由的信息

可调用该属性的params来获取数据,该属性的数据类型是对象类型,包含了当前动态路由的键值对

JS

data() {
    return {
      userId: this.$route.params.userId
    }
}

路由懒加载

如果按照以前的方式配置路由,在页面加载时会一次性加载所有的js文件,会使得网页加载变慢

这个时候build工程文件,会生成以下三个文件

  • app.js ==> 保存的是我们自己编写的代码
  • manifest.js ==> 保存的是一些底部支撑代码
  • vendor.js ==> 保存的是外部文件代码,如Vue

如果使用路由懒加载,在加载文件的时候只会在调用那个路由时才会加载对应的JS文件

官方文档

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

结合 Vue 的异步组件 (opens new window)和 Webpack 的代码分割功能 (opens new window),轻松实现路由组件的懒加载。

首先,可以将异步组件定义为返回一个 Promise 的工厂函数 (该函数返回的 Promise 应该 resolve 组件本身):

const Foo = () =>
  Promise.resolve({
    /* 组件定义对象 */
  })

第二,在 Webpack 2 中,我们可以使用动态 import (opens new window)语法来定义代码分块点 (split point):

import('./Foo.vue') // 返回 Promise

结合这两者,这就是如何定义一个能够被 Webpack 自动代码分割的异步组件。

const Foo = () => import('./Foo.vue')

现在来将我们以前的代码设置成懒加载模式

只需要做很简单的改变,通俗来讲就是,将以前的

import home from "../components/home";
import show from "../components/show";
import user from "../components/user";

改成

const home = () => import('../components/home')
const show = () => import('../components/show')
const user = () => import('../components/user')

这样一来,当我们build工程文件时,除了生成以上3个文件外,还会额外生成0,1,2这3个JS文件

这三个JS文件对应的便是这三个路由调用时对应的JS文件

嵌套路由

嵌套路由,就是在路由页面再进行路由的分配

例如,我们想在home页面再进行message和news的路由分配

首先肯定是要定义好这两个组件

然后在router.js里面设置路由,使用children关键字

children里面设置路由信息,也是设置pathcomponent

{
    path: '/home',
    component: home,
    children: [
      {
        path: '/home/message',
        component: home_message
      },
      {
        path: '/home/news',
        component: home_news
      }
    ]
},

接着在组件内定义router-linkrouter-view

例如,这里我们是在home里面定义的

在home里设置router-linkrouter-view

信息
新闻

通过query传递数据

之前设置动态路由时是通过router里的对象进行传递的,其实还有一种传递数据的方式是query(查询),这种传递数据的方式有点类似于get提交数据

和之前配置路由相同,首先定义组件,然后在router.js设置路由组件

不同的是在组件使用时,to的值是以对象的形式传递的

例如

用户信息
    
    

{{$route.query.name}}

{{$route.query.sex}}

{{$route.query.hobby}}

我们使用path与query属性

在取数据时使用query属性便可取到相应的值

导航守卫

全局前置守卫

正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

记住参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

在路由跳转时,如果我们需要添加一些事件,便可以调用该方法

比如,我们想在跳转时,将页面的title进行更改

首先需要在route对象里面添加属性,我们将route属性的meta属性重写

例如

{
    path: '/show',
    component: show,
    meta: {
      title: '展示'
    }
},

这样每一个route对象便有一个对应的值了

接着使用 router.beforeEach 注册一个全局前置守卫:

例如

router.beforeEach((to, from, next) => {
  document.title = to.matched[0].meta.title
  console.log(to)
  next()
})

其中to和from的参数是router类型,分别表示从哪个路由来要到哪个路由去

next是方法,可以进行重定向,记住全局前置守卫里面一定要有这个方法,不然跳转不生效

matched是数组,大致可以理解为是路由嵌套,我们始终选择第一个

全局后置守卫

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
  // ...
})

路由独享的守卫

你可以在路由配置上直接定义 beforeEnter 守卫:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

这些守卫与全局前置守卫的方法参数是一样的。


除此之外,还有全局解析守卫,组件内的守卫等等

keep-alive

在路由页面配置时,实现页面跳转实际上是不断创建组件与销毁组件的过程,若不希望组件被销毁,就可以使用keep-alive

使用方法:

将需要保留的组件放置在keep-alive标签中

例如:


      

在使用keep-alive时还提供了两个方法:

  • activated
  • deactivated

这两个方法在组件处于活跃状态或者不活跃状态时使用

该方法须在keep-alive包含的组件中调用


keep-alive还包含两个关键字:

  • include
  • exclude

分别表示包含的组件和不包含的组件

如果我们不希望某个组件保留,就可以使用关键字exclude

例如


      

其中exclude的参数是组件名称

切记,exclude的参数不可以含有空格