整理目的:

  • 了解 VueRouter 的特性。
  • 了解 VueRouter 的使用方法。
  • 了解 VueRouter 的实现思路。
  • 了解 VueRouter 的核心概念。

VueRouter 的特性

VueRouter 的目的是为了完善 Vue 单页面应用生态的实现。

其主要功能特性为:

  • 嵌套路由/视图表
  • 模跨化的、基于组件的路由配置
  • 过渡动画
  • history/hash 模式
  • 自定义滚动条行为

后续需要重点整理基于这些特性的源码实现思路。

VueRouter 的使用方法

VueRouter 的使用包括以下几个方面:

  • route 导航配置
  • 路由传参
  • 导航跳转
  • 导航守卫
  • 路由模式配置
  • 嵌套命名视图

route 导航配置&传参

添加 route 有两种方式:1. 在 Router 对象初始化时设置 routes。2, 后续通过 router.addRoutes 动态添加。

一个 route 包含以下要素:pathnamepropscomponentmetachildrenredirectalias

通过 children 可以实现路由嵌套。

通过 pathprops 配置可以实现路由传参。

  1. { path: '/promotion/from-newsletter', component: Promotion, props: { newsletterPopup: false } }

使用函数模式的 props 可以将静态值与基于路由的值结合等等。

  1. { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }

components 不仅可以展示一个视图,也可以展示多个视图即嵌套命名视图

  1. <router-view class="view one"></router-view>
  2. <router-view class="view two" name="a"></router-view>
  3. <router-view class="view three" name="b"></router-view>
  1. {
  2. path: '/',
  3. components: {
  4. default: Foo,
  5. a: Bar,
  6. b: Baz
  7. }
  8. }

通过 redirect 可以实现路由的重定向:

  1. { path: '/a', redirect: { name: 'foo' }}

要注意区分重定向和重命名的区别:

**/a** 的别名是 **/b**,意味着,当用户访问 **/b** 时,URL 会保持为 **/b**,但是路由匹配则为 **/a**,就像用户访问 **/a** 一样。

  1. { path: '/a', component: A, alias: '/b' }

导航守卫

VueRouter 的导航守卫分为全局导航守卫、路由独享守卫、组件内的守卫。

全局导航守卫

全局导航守卫通常用于登录验证以及权限验证,在使用中要注意调用顺序和 next 函数的用法。

  • router.beforeEach((to, from, next)=>{next()})
    • **next()**:进行管道中的下一个钩子。
    • **next(false)**: 中断当前的导航。如果浏览器的 URL 改变了,那么 URL 地址会重置到 from 路由对应的地址。
    • **next('/')** 或者 **next({ path: '/' })**: 跳转到一个不同的地址。
    • **next(error)**: (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 [router.onError()](https://router.vuejs.org/zh/api/#router-onerror) 注册过的回调。
  • router.afterEach((to, from) => {})
  • `router.beforeResolve((to, from, next)=>{next()})``:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

用例如下:

  1. const router = new VueRouter({ ... })
  2. router.beforeEach((to, from, next) => {
  3. // ...
  4. })

路由独享守卫

在路由配置中直接定义beforeEnter 守卫:

  1. {
  2. path: '/foo',
  3. component: Foo,
  4. beforeEnter: (to, from, next) => {
  5. // ...
  6. }
  7. }

组件内的导航

  • beforeRouteEnter
  • beforeRouteUpdate (2.2 新增)
  • beforeRouteLeave
  1. beforeRouteEnter (to, from, next) {
  2. // 在渲染该组件的对应路由被 confirm 前调用
  3. // 不!能!获取组件实例 `this`
  4. // 因为当守卫执行前,组件实例还没被创建
  5. },
  6. beforeRouteUpdate (to, from, next) {
  7. // 在当前路由改变,但是该组件被复用时调用
  8. // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
  9. // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
  10. // 可以访问组件实例 `this`
  11. },
  12. beforeRouteLeave (to, from, next) {
  13. // 导航离开该组件的对应路由时调用
  14. // 可以访问组件实例 `this`
  15. }

导航守卫调用顺序

动效

路由切换的动效提供了两种方式:全部路由动效的配置和单个路由动效的配置。这些其实还是对 transition 动效组件的不同应用。具体写法如下:

  1. <transition :name="transitionName">
  2. <router-view></router-view>
  3. </transition>
  1. const Bar = {
  2. template: `
  3. <transition name="fade">
  4. <div class="bar">...</div>
  5. </transition>
  6. `
  7. }

滚动行为

使用 scrollBehavior 方法来保持滚动位置。

  1. const router = new VueRouter({
  2. routes: [...],
  3. scrollBehavior (to, from, savedPosition) {
  4. // return 期望滚动到哪个的位置
  5. //return { x: 0, y: 0 }
  6. //return savedPosition
  7. //return {selector: to.hash}
  8. }
  9. })

具体来说可以实现滚动到指定位置、滚动到指定锚点,并且支持 Promise 返回值。

VueRouter 的实现思路

VueRouter 的核心源码分析