zoukankan      html  css  js  c++  java
  • vue-router源码阅读(一) 内部探究

    1. 前言

    vue-router版本:3.3.2

    vue-router仓库:https://github.com/vuejs/vue-router

    vue-router文档:https://router.vuejs.org/zh/

    文章时间:2020-06-16

    2 执行顺序

    首先看个简单的代码块,看看vue-router是怎么注册到vue实例上:

    // 1.注册VueRouter
    Vue.use(VueRouter);
    
    // 2.创建路由组件并设置路由
    const router = new VueRouter({
    	mode: 'hash',
    	routes: [
    		{ path: '/', component: Home }
    	]
    });
    
    // 3.创建Vue实例
    window.vueInstance = new Vue({
    	el: '#app',
    	router
    });
    

    2.1 第一步:Vue.use(VueRouter)

    调用此代码时,实际执行的vue-router/src/install.js,其内部主要执行的代码步骤如下:

    1) 设置Vue.prototype.$router属性,返回值为_router对象(全局VueRouter对象);

    2) 设置Vue.prototype.$route属性,返回值为_route对象(当前页面的route对象);

    3) 注册全局组件:router-view;

    4) 注册全局组件:router-link;

    5) 在Vue.beforeCreate事件上注入回调函数,此回调函数的执行在第三步 new Vue({router})上才触发。

    2.2 第二步:new VueRouter({options})

    这一步是生成VueRouter对象,其调用的构造函数内部代码执行步骤如下:

    1) 创建this.matcher,进行如下操作:

      ①创建pathList:路由的所有path集合,并把'*'号路径的路由移到pathList的最后。

      ②创建pathMap:key为路由的path,item为封装了的对应的RouteRecord对象,包括path、path对应的regex、components、name等等。

      ③创建nameMap:key为路由的name,item与pathMap一样,都是RouteRecord对象。

      ④this.matcher提供了2个方法:match和addRoutes。

    2) 创建this.history,此属性根据options.mode设置不同的导航模式:

      ①若mode == 'history' :表示采用HTML5 History模式。

      ②若mode == 'hash' :表示采用hash模式,默认为此模式。

      ③若mode == 'abstract' :支持所有 JavaScript 运行环境,如 Node.js 服务器端。

    2.3 第三步:new Vue({ router })

    这里主要是为了执行第一步的Vue.use(router)注入的beforeCreate回调。

    其主要执行router.init()方法,内部步骤如下:

    1) 当前router对象缓存创建的Vue实例

    this.apps.push(app);
    this.app = app;
    

    2) 根据当前页面的url获取对应的Route对象并渲染匹配的组件页面,其内部步骤如下:

      假设url为http://localhost:8080/hash-mode/#/bar?a=1#title,model为'hash'

      ①获取路径;值为:/bar?a=1#title

      ②解析路径,得到路径完整信息;值为:{ hash: "#title", params: {}, path: "/bar", query: {a: "1"}, _normalized: true }

      ③根据上面的path,找到之前存储的RouteRecord对象,创建为Route对象。

      ④调用离开组件的beforeRouteLeave守卫;若当前的url改变是从组件a→组件b,这适合调用a组件的beforeRouteLeave守卫回调。

      ⑤调用全局Router的beforeEach守卫;

      ⑥调用重用组件里的beforeRouteUpdate守卫;

      ⑦在路由配置里调用beforeEnter守卫。

      ⑧对路由配置里对应的异步组件进行解析;路由配置的组件通过 require.ensure() 或 Promise.resolve() 加载的组件才会执行这一步。

      ⑨调用进入组件里的beforeRouteEnter守卫;

      ⑩调用全局Router的beforeResolve守卫;

      ⑪导航被确认;修改当前的route为新页面的route;

      ⑫调用全局Router的afterEach守卫;

    3) 在winodw的popstate事件上注册回调,执行上一步操作( 执行第2步)。

    注意:哪怕模式选择的是'hash',当window拥有'popstate'事件时也会采用此事件,没有的话才采用'hashchange'事件。为什么呢?因为'popstate'在IE上是不支持,'hashchange'从IE8开始支持。

    4) 在Vue的destroyed钩子注册回调:注销第4步在window注册的回调。

     

  • 相关阅读:
    在日本被禁止的コンプガチャ設計
    Starling常见问题解决办法
    Flixel引擎学习笔记
    SQLSERVER中修复状态为Suspect的数据库
    T4 (Text Template Transformation Toolkit)实现简单实体代码生成
    创建Linking Server in SQL SERVER 2008
    Linq to Sql 与Linq to Entities 生成的SQL Script与分页实现
    Linq to Entity 的T4 模板生成代码
    在VisualStudio2008 SP1中调试.net framework 源代码
    使用HttpModules实现Asp.net离线应用程序
  • 原文地址:https://www.cnblogs.com/polk6/p/13090615.html
Copyright © 2011-2022 走看看