Vue-Router 源码学习之咱们从API中看些门道

前言

此次真的是过久过久没见了,伙伴们。 学习真的没有松懈,只是季度末要冲一冲绩效,一会儿把时间都充值了。(ps:我看应该是个人脑子须要充值)前端

系列文章: Vue-Router源码分析之index.jsvue

Vue-Router源码分析之install方法面试

正文

为何要从API中看门道呢?

咱们在使用vue-router的时候,其实就是按照API进行操做,源码其实就是API的另外一种形式,在个人学习中,我发现一味的干货有时效果并很差,由其是深刻思考性比较强的内容。所以本篇文章因此做为一个过渡章节,让咱们一块儿聊一聊承上启下的内容,聊聊API:vue-router

咱们的push有哪些状况?

在实际工做中,编程式导航要比<router-link>标签使用的多的多,复杂逻辑中嵌套路由跳转都是要使用编程式导航。编程

// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: 123 }})
router.push({ path: `/user/${userId}` })
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
复制代码

在编程式路由中,咱们能够接收一个对象、一个字符串,对象的key有path、name、query、params等等,可是须要相互组合。数组

这么多状况vue-router要对push这么多状况作一个处理,咱们push接收的参数的类型是什么?用flow设定为Location、RawLocationapp

用flow.js设定的类型
declare type Location = {
  _normalized?: boolean;
  name?: string;
  path?: string;
  hash?: string;
  query?: Dictionary<string>;
  params?: Dictionary<string>;
  append?: boolean;
  replace?: boolean;
}
declare type RawLocation = string | Location
复制代码

翻译过来就是未处理的、生的路径。因此咱们的push操做传递的是一个生冷的路径,通过一次match的处理源码分析

源码内容:
const route = this.router.match(location, this.current)
复制代码

变成vue-router所须要的结构,route类型post

declare type Route = {
  path: string;
  name: ?string;
  hash: string;
  query: Dictionary<string>;
  params: Dictionary<string>;
  fullPath: string;
  matched: Array<RouteRecord>;
  redirectedFrom?: string;
  meta?: any;
}
复制代码

因此从API结合表层源码来看,咱们在进行编程式导航时的过程,先将未处理的路径(ps:vue-router对这种未处理路径无法直接进行跳转等操做)处理成一个规范的route类型,而后进行具体的路由跳转内容。学习

命名路由与视图

<router-view class="view one"></router-view>
<router-view class="view two" name="a"></router-view>
<router-view class="view three" name="b"></router-view>

const router = new VueRouter({
  routes: [
    {
      path: '/',
      components: {
        default: Foo,
        a: Bar,
        b: Baz
      }
    }
  ]
})
复制代码

一个组件内能够有多个router-view组件,我接触的几个项目都是维护一个根结点的router-view。大部分都是这种结构

<template>
  <div id="app">
    <router-view/>
  </div>
</template>
复制代码

咱们一个路径下能够展现多个路由视图组件吗?

答案固然是确定的,官方的命名视图的例子(jsfiddle.net/posva/22wgk… 能够看到,咱们在同一个路径下能够放置多个<router-link>,这里面的name与咱们在构造vue-router时设置的components有对应,咱们通常都是component : xxx;对应一个组件。如何对应多个的呢?

源码内容:
components: route.components || { default: route.component },
复制代码

其实人家自己但愿你用components,你要只用一我的家就给你包装成一个map,key呢就是默认值的意思。

再看看咱们的vue-router2开始的路由守卫

路由守卫有哪些呢?

  • 1:全局的beforeEach

  • 2:单个路由配置的beforeEnter

  • 3:全局的afterEach

  • 4:组件内的路由守卫:

    beforeRouteEnter

    beforeRouteUpdate (2.2 新增)

    beforeRouteLeave

  • 5:全局的beforeResolve(vue-router2.5新增)

别的守卫还有吗?这么看来是没有了。

全局的beforeEnter、afterEach、beforeResolve为何会做用在每个路由配置中呢?在index一章中,咱们有三个存放守卫的数组你们还有印象吗?

beforeHooks: Array<?NavigationGuard>;
resolveHooks: Array<?NavigationGuard>;
afterHooks: Array<?AfterNavigationHook>;
复制代码

在router实例中存储这些。因此咱们在作路由跳转的时候能够拿到这些守卫,其他的守卫怎么办?只好在跳转的时候具体状况具体执行,

守卫分为三个种类:

1:离开组件以前,2:进入组件(先后都有守卫) 3:更新组件以前

因此一个路由的跳转必定伴随着如下几个步骤

  • 1:跳转咱们称之为transitionTo

  • 2:那么跳转中进行一个confirmTransiton(跳转前的准备)

  • 3:跳转结束时进行一个updateRoute的过程

上文提到的confirmTransition:先收集到全部的守卫,把前置守卫们(前置!!!)链接成一个数组,跳转前挨个执行,前置守卫执行完怎么办?都经过来,那就更新当前路由,更新完当前路由就执行一下后置守卫。 vue-router源码中:

核心的路由跳转方法就是transitionTo: 具体内容是由confirmTransition与updateRoute实现的

其他的一些这这那那的容错,并不影响主流程。

总结一下

对于push、replace传递的未处理的路径,进行处理成vue-router能够操做的路径。

对于多个router-view,咱们能够选择children,components来实现。

路由守卫为何能够有全局的,每一个路由均可以用,由于在router实例上,咱们每次跳转均可以找到。

路由跳转经历了confirm确认与update更新两步

结束语

中秋节刚刚过去,十一立刻就到了

没有来得及给你们带来祝福,但愿你们十一的时候每次路由跳转都不堵车!

每个前端er(boy and girl) 大家都不是一我的在战斗

我是一个应届生,最近和朋友们维护了一个公众号,内容是咱们在从应届生过渡到开发这一路所踩过的坑,已经咱们一步步学习的记录,若是感兴趣的朋友能够关注一下,一同加油~

我的公众号:IT面试填坑小分队
相关文章
相关标签/搜索