Vue-Router v3 使用详解

315 阅读3分钟

前言

Vue Router 是 vue官方的路由管理器,其中v3版本适用于vue2,v4版本适用于vue3。本文单将v3版本

Vue Router 官方文档

安装和基本使用

安装

npm install vue-router

使用

新建src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
const constantRoutes = [
  {
    path: "/login",
    component: () => import("@/views/login/index")
  }
]
const createRouter = () =>
  new Router({
    routes: constantRoutes,
  })
// 创建路由实例,并默认导出
const router = createRouter()
export default router

main.js中:

import router from "@/router"
new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

Router 实例属性和方法

属性

  • app: Vue实例
  • mode: 路由使用的模式("hash" | "history" | "abstract")
  • currentRoute: 当前路由信息对象

方法

导航类方法

  1. push
// 字符串
router.push('home')

// 对象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

注意:如果提供了 pathparams 会被忽略。

  1. replace

用法和push类似,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。

push和replace方法会返回一个Promise

  1. go

这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)

// 后退一步记录,等同于 history.back()
router.go(-1)

// 前进 3 步记录
router.go(3)

// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
  1. back

后退一步,等价于router.go(-1)

  1. forward

后退一步,等价于router.go(1)

路由钩子相关方法

  1. beforeEach 全局前置路由
router.beforeEach((to, from, next) => {
  // ...
})

一定要调用next方法来 resolve 这个钩子:

  • next(): 进行管道中的下一个钩子。
  • next(false): 中断当前的导航。
  • next('/') 或者 next({ path: '/' }) : 跳转到一个不同的地址。
  • next(error):如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError() 注册过的回调。
  1. beforeResolve

这和 router.beforeEach 类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

  1. afterEach

全局后置钩子

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

添加路由

  1. addRoute
  • 添加一条新路由规则。如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。
addRoute(route: RouteConfig): () => void
  • 添加一条新的路由规则记录作为现有路由的子路由。如果该路由规则有 name,并且已经存在一个与之相同的名字,则会覆盖它。
addRoute(parentName: string, route: RouteConfig): () => void
  1. getRoutes 获取所有活跃的路由记录列表。
getRoutes(): RouteRecord[]

路由信息对象(RouteRecord)

一个路由对象  表示当前激活的路由的状态信息。

路由对象是不可变 (immutable) 的,每次成功的导航后都会产生一个新的对象。

路由对象出现在多个地方:

  • 在组件内,即 this.$route
  • 在 $route 观察者回调内
  • router.match(location) 的返回值
  • 导航守卫的参数:
router.beforeEach((to, from, next) => {
  // `to` 和 `from` 都是路由对象
})

路由对象属性

  • path

字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"

  • params

一个 key/value 对象,包含了动态片段和全匹配片段,如果没有路由参数,就是一个空对象。

  • query

一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。

  • hash

当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串。

  • fullPath

完成解析后的 URL,包含查询参数和 hash 的完整路径。

  • matched

一个数组,包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 数组)。

const router = new VueRouter({
  routes: [
    // 下面的对象就是路由记录
    {
      path: '/foo',
      component: Foo,
      children: [
        // 这也是个路由记录
        { path: 'bar', component: Bar }
      ]
    }
  ]
})
  • name

当前路由的名称,如果有的话

  • redirectedFrom

如果存在重定向,即为重定向来源的路由的名字

RouteConfig

在构建Router时,传入的的参数routes的类型为Array<RouteConfig>

interface RouteConfig = {
  path: string,
  component?: Component,
  name?: string, // 命名路由
  components?: { [name: string]: Component }, // 命名视图组件
  redirect?: string | Location | Function,
  props?: boolean | Object | Function,
  alias?: string | Array<string>,
  children?: Array<RouteConfig>, // 嵌套路由
  beforeEnter?: (to: Route, from: Route, next: Function) => void,
  meta?: any,

  // 2.6.0+
  caseSensitive?: boolean, // 匹配规则是否大小写敏感?(默认值:false)
  pathToRegexpOptions?: Object // 编译正则的选项
}

内置组件

<router-link>

  • to: 必填。
<!-- 字符串 -->
<router-link to="home">Home</router-link>
<!-- 渲染结果 -->
<a href="home">Home</a>

<!-- 使用 v-bind 的 JS 表达式 -->
<router-link v-bind:to="'home'">Home</router-link>

<!-- 不写 v-bind 也可以,就像绑定别的属性一样 -->
<router-link :to="'home'">Home</router-link>

<!-- 同上 -->
<router-link :to="{ path: 'home' }">Home</router-link>

<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: 123 }}">User</router-link>

<!-- 带查询参数,下面的结果为 /register?plan=private -->
<router-link :to="{ path: 'register', query: { plan: 'private' }}"
  >Register</router-link
>
  • replace: boolean

设置 replace 属性的话,当点击时,会调用 router.replace() 而不是 router.push()

<router-view>

<router-view> 组件是一个 functional 组件,渲染路径匹配到的视图组件。<router-view> 渲染的组件还可以内嵌自己的 <router-view>,根据嵌套路径,渲染嵌套组件。

配合 <transition> 和 <keep-alive> 使用:

<transition>
  <keep-alive>
    <router-view></router-view>
  </keep-alive>
</transition>

注入的属性

通过在 Vue 根实例的 router 配置传入 router 实例,下面这些属性成员会被注入到每个子组件。

  • this.$router

    router 实例。

  • this.$route

    当前激活的路由信息对象)。这个属性是只读的,里面的属性是 immutable (不可变) 的,不过你可以 watch (监测变化) 它。

组件内守卫

  • beforeRouteEnter(to, from, next)

不能 访问 this,不过可以通过传一个回调给 next来访问组件实例

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通过 `vm` 访问组件实例
  })
}
  • beforeRouteUpdate(to, from, next) (2.2 新增)

在当前路由改变,但是该组件被复用时调用。 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。

  • beforeRouteLeave

这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消。

奇技淫巧

重置路由

在一般的后台管理系统中,不同的用户可能有不同的路由权限,但又有通用的路由,一般是在登录后,根据用户权限加载不同的路由。那么在用户注销后,如何重置路由呢?

function resetRouter() {
  const newRouter = createRouter();
  router.matcher = newRouter.matcher; // 重置 路由
}

面试题

params和query传参的使用和区别

  1. query

类似于get请求,query传过去的参数会拼接到url中。query既可以配合path,也可以配合name使用。

  1. params

一般params传过去的参数不会显示url上,只能配合name使用,如果出现了path, params会失效。

如果用到了动态路由:‘/user/:id’,传递过去的就是params参数,会拼接显示在地址栏中,比如:/user/13。

如何监听路由参数的变化

  1. watch
watch: {
    '$route'(to, from) {
    }
  },
  1. 使用组件守卫beforeRouteUpdate(to, from, next)