详解vue-router 初始化时做了什么


Posted in Javascript onJune 11, 2018

最近因为业务需要,实现了一个简单的前端 router,正好也来看一下 vue router 是怎么实现的。这次先来一起看看 vue-router 初始化时做了什么。

vue router 的初始化使用步骤

我们首先来看 vue-router 的使用步骤,然后再分别去看各个步骤都发生了什么。

使用 vue-router 需要经过一下几个步骤:

引入 vue-router:

import VueRouter from 'vue-router';

利用 vue 的插件机制,加载 vue-router:

Vue.use(VueRouter);

实例化 VueRouter:

const router = new VueRouter({
routes
})

实例化 Vue:

const app = new Vue({
router
}).$mount('#app');

Vue 的插件机制

vue 提供了一个 use 方法,来加载插件:

Vue.use = function (plugin: Function | Object) {
 const installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
 if (installedPlugins.indexOf(plugin) > -1) {
  return this;
 }

 // additional parameters
 const args = toArray(arguments, 1);
 args.unshift(this);
 if (typeof plugin.install === 'function') {
  plugin.install.apply(plugin, args);
 } else if (typeof plugin === 'function') {
  plugin.apply(null, args);
 }
 installedPlugins.push(plugin);
 return this;
}

该方法首先检查插件是否已经加载,如果已经加载,直接返回 this。

如果没有加载过,会取所有的参数,并将 this 放在第一个。优先执行 plugin.install 方法,若不能执行,则直接执行 plugin 自身。

最后将 plugin push 到插件列表中。

那么我们就需要看 VueRouter 的 install 方法做了什么,VueRouter 类定义在 src/index.js 文件中。

利用 vue 的插件机制,加载 vue-router

入口文件 index.js 对外 export 了一个 VueRouter 类。VueRouter 类包含了 router 的各种方法,我们直接先来看一下 install 方法。

install 方法在 index.js 中绑定在 VueRouter 类上:

import { install } from './install'
VueRouter.install = install

它的实际实现是在 ./install.js 中,install 方法主要做了以下几个事情:

1、设置了两个 mixin:beforeCreate 和 destroyed。

Vue.mixin({
 beforeCreate () {
  if (isDef(this.$options.router)) {
   this._routerRoot = this
   this._router = this.$options.router
   this._router.init(this)
   Vue.util.defineReactive(this, '_route', this._router.history.current)
  } else {
   this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
  }
  registerInstance(this, this)
 },
 destroyed () {
  registerInstance(this)
 }
})

2、在 Vue 上绑定 $route 和 $router。

Object.defineProperty(Vue.prototype, '$router', {
 get () { return this._routerRoot._router }
})

Object.defineProperty(Vue.prototype, '$route', {
 get () { return this._routerRoot._route }
})

3、注册两个组件,View 和 Link。

Vue.component('RouterView', View)
Vue.component('RouterLink', Link)

4、设置 beforeRouteEnter、beforeRouteLeave 和 beforeRouteUpdate 的 merge 策略。merge 策略的介绍可以见 这里 ,简单来说就是有重复的值时如何合并。

const strats = Vue.config.optionMergeStrategies
// use the same hook merging strategy for route hooks
strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created

实例化 VueRouter

我们来看一下 VueRouter 的构造函数。首先,constructor 会初始化一些属性:

this.app = null
this.apps = []
this.options = options
this.beforeHooks = []
this.resolveHooks = []
this.afterHooks = []
this.matcher = createMatcher(options.routes || [], this)

其中 matcher 比较重要,后面会详细说。

之后会决定使用哪种模式:

let mode = options.mode || 'hash'
this.fallback = mode === 'history' && !supportsPushState && options.fallback !== false
if (this.fallback) {
 mode = 'hash'
}
if (!inBrowser) {
 mode = 'abstract'
}
this.mode = mode

switch (mode) {
 case 'history':
  this.history = new HTML5History(this, options.base)
  break
 case 'hash':
  this.history = new HashHistory(this, options.base, this.fallback)
  break
 case 'abstract':
  this.history = new AbstractHistory(this, options.base)
  break
 default:
  if (process.env.NODE_ENV !== 'production') {
   assert(false, `invalid mode: ${mode}`)
  }
}

由于 history 模式中的pushstate方法还有一些浏览器没有支持。history 模式在浏览器不支持时会回退到hash模式。

之后根据不同模式选择实例化不同模式的history类,可以看到 hash 模式和 history 模式分别对应了 HashHistory 和 HTML5History 两个类。

此外,如果是服务器端渲染,需要进行 router 匹配来获取要渲染的页面。此时服务器环境中没有history api,因此要自行抽象实现一个,就是 AbstractHistory。

实例化 Vue

实例化为Vue 类时,会将 VueRouter 的实例传入,这个变量放在 this.$options.router 中。由于 vue router 时以插件形式引入的,因此 这个 this.$options.router 还是给 vue router 自身来用的。

vue router 初始化所做的事情就是这些,下篇博客我们来一起看一下 vue router 实际运行时发生了什么。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
extjs 学习笔记(一) 一些基础知识
Oct 13 Javascript
jQuery 工具函数学习资料
Apr 29 Javascript
JQuery的ajax获取数据后的处理总结(html,xml,json)
Jul 14 Javascript
IE6下通过a标签点击切换图片的问题
Nov 14 Javascript
基于jquery的二级联动菜单实现代码
Apr 25 Javascript
jquery ajax学习笔记2 使用XMLHttpRequest对象的responseXML
Oct 16 Javascript
详解angular用$sce服务来过滤HTML标签
Apr 11 Javascript
bootstrap+jQuery 实现下拉菜单中复选框全选和全不选效果
Jun 12 jQuery
angularjs中$http异步上传Excel文件方法
Feb 23 Javascript
JavaScript如何处理移动端拍摄图片旋转问题
Nov 16 Javascript
vue+node 实现视频在线播放的实例代码
Oct 19 Javascript
微信小程序学习之自定义滚动弹窗
Dec 20 Javascript
node中间层实现文件上传功能
Jun 11 #Javascript
几个你不知道的技巧助你写出更优雅的vue.js代码
Jun 11 #Javascript
Vue.js 中取得后台原生HTML字符串 原样显示问题的解决方法
Jun 10 #Javascript
实例详解Node.js 函数
Jun 10 #Javascript
微信小程序实现倒计时调用相机自动拍照功能
Jun 10 #Javascript
深入浅析Vue中的Prop
Jun 10 #Javascript
vue项目部署上线遇到的问题及解决方法
Jun 10 #Javascript
You might like
php数组中删除元素的实现代码
2012/06/22 PHP
PHP过滤★等特殊符号的正则
2014/01/27 PHP
PHP+AJAX实现投票功能的方法
2015/09/28 PHP
JavaScript的Function详细
2006/11/14 Javascript
Jquery CheckBox全选方法代码附js checkbox全选反选代码
2010/06/09 Javascript
jquery全选/全不选/反选另一种实现方法(配合原生js)
2013/04/07 Javascript
巧用jquery解决下拉菜单被Div遮挡的相关问题
2014/02/13 Javascript
nodeJS代码实现计算交社保是否合适
2015/03/09 NodeJs
JS+CSS实现滑动切换tab菜单效果
2015/08/25 Javascript
jQuery实现分隔条左右拖动功能
2015/11/21 Javascript
完美实现八种js焦点轮播图(上篇)
2016/07/18 Javascript
1秒50万字!js实现关键词匹配
2016/08/01 Javascript
封装的dialog插件 基于bootstrap模态对话框的简单扩展
2016/08/10 Javascript
详解Javascript百度地图接口开发文档中的类和方法
2017/02/07 Javascript
vue中计算属性(computed)、methods和watched之间的区别
2017/07/27 Javascript
JavaScript模拟实现封装的三种方式及写法区别
2017/10/27 Javascript
Vue完整项目构建(进阶篇)
2018/02/10 Javascript
Angular6笔记之封装http的示例代码
2018/07/27 Javascript
Node.JS获取GET,POST数据之queryString模块使用方法详解
2020/02/06 Javascript
node.js 使用 net 模块模拟 websocket 握手进行数据传递操作示例
2020/02/11 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
jquery实现简单每周轮换的日历
2020/09/10 jQuery
Python实现定时任务
2017/02/08 Python
老生常谈进程线程协程那些事儿
2017/07/24 Python
Python实现时钟显示效果思路详解
2018/04/11 Python
python Tcp协议发送和接收信息的例子
2019/07/22 Python
基于python分析你的上网行为 看看你平时上网都在干嘛
2019/08/13 Python
Python中如何添加自定义模块
2020/06/09 Python
详解python logging日志传输
2020/07/01 Python
网上常见的一份Linux面试题(多项选择部分)
2014/09/09 面试题
结婚典礼证婚词
2014/01/11 职场文书
员工工作表现评语
2014/04/26 职场文书
夏季药店促销方案
2014/08/22 职场文书
三严三实民主生活会发言稿
2014/10/13 职场文书
iPhone13 Pro外观确定,升级4800万镜头,4月20日发新品
2021/04/15 数码科技
世界十大狙击步枪排行榜
2022/03/20 杂记