felix-cao / Blog

A little progress a day makes you a big success!
31 stars 4 forks source link

Vue 路由管理器(Vue Router)的动态路由匹配 #156

Open felix-cao opened 5 years ago

felix-cao commented 5 years ago

Vue RouterVue.js 官方的路由管理器。它和 Vue.js 的核心深度集成 (deeply integrates),让构建单页面应用变得易如反掌。本文主要根据官方文档介绍 Vue 路由基础知识。

路由安装方法:

npm install vue-router --save

Vue.js + Vue Router 的项目中,我们通常是将组件 (components) 映射到路由 (routes),建立一种对应关系,然后通过 <router-view></router-view> 占位符告诉 Vue Router 在哪里渲染它们,这种方式跟 Angularui-router 如出一辙。

动态路由匹配实际上是一种模式匹配,是把符合某种模式匹配到的所有路由,全都映射到路由配置中的组件去处理,通过路由配置建立路由名称、路径 path、组件 components 之间的映射关系。

一、动态路径参数

动态路由匹配的实现是通过 “动态路径参数”(dynamic segment) 来实现的。

比如我们有一个用户 User 组件,所有的用户都会使用这个组件来处理:

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

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User } // 动态路径参数 以冒号开头
  ]
})

那么,id1001000 的用户,其 path 表现为 /user/100/user/1000,都将映射到这个路由。

在路由配置中,动态路径参数是通过使用 : 标记,参数值会被匹配到 this.$route.params 中, 现在我们更新 User 的模板,输出当前用户的 ID

const User = {
  template: '<div>User {{ $route.params.id }}</div>'
}

二、多段 “路径参数”

我们也可以在一个路由中设置多段“路径参数”,对应的值都会设置到 $route.params 中。例如:

模式 匹配路径 $route.params
/user/:id/:username /user/100/foo {id: 100, name: foo}
/user/:id/name/:username /user/100/name/bar {id: 100, name: bar}

除了 $route.params 外,$route 对象还提供了其它有用的信息,例如,$route.query (如果 URL 中有查询参数)、$route.hash 等等。你可以查看 API 文档 的详细说明。

三、使用通配符

在很多模式匹配中,都有使用通配符 * 的概念,同样,聪明的 Vue 作者,也在路由配置中的path 参数配置中使用了通配符,通配符的使用使得路由管理更加自由、更加灵活、更加方便, 而常规参数只会匹配被 / 分隔的 URL 片段中的字符。

{
  path: '*' // 会匹配所有路径
}
{
  path: '/user-*'  // 会匹配以 `/user-` 开头的任意路径
}

路由 { path: '*' } 通常用于客户端 404 错误。

当使用一个通配符时,$route.params 内会自动添加一个名为 pathMatch 参数。它包含了 URL 通过通配符被匹配的部分:

// 给出一个路由 { path: '/user-*' }
this.$router.push('/user-admin')
this.$route.params.pathMatch // 'admin'
// 给出一个路由 { path: '*' }
this.$router.push('/non-existing')
this.$route.params.pathMatch // '/non-existing'

四、高级匹配模式和匹配优先级

vue-router 使用 path-to-regexp 作为路径匹配引擎,所以支持很多高级的匹配模式,例如:可选的动态路径参数、匹配零个或多个、一个或多个,甚至是自定义正则匹配。查看它的 文档 学习高阶的路径匹配,还有 这个例子 展示 vue-router 怎么使用这类匹配。

有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高。

五、响应路由参数的变化

当使用路由参数时,例如从 /user/foo 导航到 /user/bar原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

复用组件时,想对路由参数的变化作出响应的话,你可以简单地 watch (监测变化) $route 对象:

const User = {
  template: '...',
  watch: {
    '$route' (to, from) {
      // 对路由变化作出响应...
    }
  }
}

或者使用 2.2 中引入的 beforeRouteUpdate 导航守卫:

const User = {
  template: '...',
  beforeRouteUpdate (to, from, next) {
    // react to route changes...
    // don't forget to call next()
  }
}

beforeRouteUpdate 官方叫导航守卫,共有5种,可以阅读 navigation guard , 我的理解可以改个名词叫 路由生命周期函数