• 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注册的回调。

     

  • 相关阅读:
    CVTE前端一面
    转载几篇看过的几篇使用技术博文
    Vue自定义指令
    node项目初始化的一些配置
    vue+element 实现在表格内插入其他组件,每行数据独立存储
    jquery如何实现当页面下拉到一定位置时,右下角出现回到顶部图标
    css实现垂直居中的方法整理
    css3兼容性检测工具
    css变换与动画详解
    手机访问电脑端网站偏问题解决
  • 原文地址:https://www.cnblogs.com/polk6/p/13090615.html
Copyright © 2020-2023  润新知