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

最近因为业务需要,实现了一个简单的前端 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 实际运行时发生了什么。

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

(0)

相关推荐

  • 详解vue-router 命名路由和命名视图

    说明:vue-router的几个文章中例子是连贯的,因此对哪块有疑问请翻阅按发表时间排序的其他文章. 一.概述 给路由定义不同的名字,根据名字进行匹配 给不同的router-view定义名字,router-link通过名字进行对应组件的渲染. 二.代码展示: 目录视图 1.命名路由 2.命名视图 index.js import Vue from 'vue' import Router from 'vue-router' import Goodlists from '@/Goodlists/goo

  • vue的传参方式汇总和router使用技巧

    vue传参方法一 1,路由配置 { path: '/describe/:id', name: 'Describe', component: Describe } 2,使用方法 // 直接调用$router.push 实现携带参数的跳转 this.$router.push({ // 这个id是一个变量,随便是什么值都可以 path: /describe/${id}`, }) 3,获取方法(在describe页面) $route.params.id 使用以上方法可以拿到上个页面传过来的id值 vue

  • 讲解vue-router之什么是编程式路由

    前言:编程式路由在我们的项目使用过程中最常用的的方法了. GitHub:https://github.com/Ewall1106/mall/ 什么是编程式路由呢?就是通过写js代码来实现页面的跳转 1.$router.push('name'); 或者 $router.push({path: 'name'}); 首先我们来讲讲简单的,上面两个方法记住,等效的. ① 还是在test.vue组件里面写个div并给它添加一个click跳转事件: div上添加一个click点击事件 ② 在view文件下新

  • 讲解vue-router之命名路由和命名视图

    前言:前面我们把动态路由.嵌套路由等讲完了,说道完命名路由和命名视图,vue-router的基本使用方法就算是完篇了,还想仔细探究的同学可以去官网翻阅,加深理解. 1.首先来说说什么是命名路由? ① 官方文档的解释:https://router.vuejs.org/zh/guide/essentials/named-routes.html 就是在routers配置路由名称的时候给路由定义不同的名字,这样的好处就是可以在使用router-link的to属性跳转路由的时候传一个对象从而实现与rout

  • 讲解vue-router之什么是嵌套路由

    上一次给大家简单说了下什么是动态路由现在我们来讲讲嵌套路由. GitHub:https://github.com/Ewall1106/mall 1.嵌套路由的使用场景是什么呢? 大家都知道选项卡,在选项卡中,顶部有数个导航栏,中间的主体显示的是内容:这个时候,整个页面是一个路由,然后点击选项卡切换不同的路由来展示不同的内容,这个时候就是路由中嵌套路由. 2.具体是怎么实现的? ① 为了演示,我们现在view文件夹下新建一个title1.vue和title2.vue用来存放不同的内容 title1

  • vue router+vuex实现首页登录验证判断逻辑

    首页登录逻辑要求在页面上判断是否获取到登录token ,没有获取到则跳转到登录页.登录成功后,跳转到前一个页面. 1.vue router 路由判断首先我们想到的是router.beforeEach 前置导航守卫 ,这个方法接受三个参数 to from next . to参数为即将跳转的路由路径,from为当前导航正要离开的路由,next方法用来resolve这个钩子. 下面以工作中写的一个判断为为例子: router.beforeEach(async (to, from, next) => {

  • 浅析前端路由简介以及vue-router实现原理

    路由这个概念最先是后端出现的.在以前用模板引擎开发页面时,经常会看到这样 http://www.xxx.com/login 大致流程可以看成这样: 浏览器发出请求 服务器监听到80端口(或443)有请求过来,并解析url路径 根据服务器的路由配置,返回相应信息(可以是 html 字串,也可以是 json 数据,图片等) 浏览器根据数据包的 Content-Type 来决定如何解析数据 简单来说路由就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中

  • 讲解vue-router之什么是动态路由

    前言: 今天我来给大家说道说道v-router,这是个什么东西?我们先从动态路由讲起. GitHub:https://github.com/Ewall1106/mall/tree/master 1.动态路由有一个什么适用场景呢? 比如在写商品详情页面的时候,页面结构都一样,只是商品id的不同,所以这个时候就可以用动态路由动态. 2.官方文档 首先我们来看看官方文档上是怎么解释动态路由的?(https://router.vuejs.org/zh-cn/) 你可以在一个路由中设置多段"路径参数&qu

  • vue-router3.0版本中 router.push 不能刷新页面的问题

    在 github 的 vue-router 中找到同样的一个问题:3.0.1版本通过router实例无法跳转 昨天发现有些路由不能正常跳转,找了一下发现都是那些实例化后使用 router.push 而不是直接使用 this.$router.push 的地方. 出现的情况是 router.push 后,url变化了,但是页面没有刷新,手动刷新一下才出现应有的画面. 我看了一下 package.json,我的 vue 和 axios 是没有写版本号,但 vue-router 明明写了版本号,怎么可能

  • 关于vue-router的那些事儿

    一.引子 要学习vue-router就要先知道这里的路由是什么?为什么我们不能像原来一样直接用标签编写链接哪?vue-router如何使用?常见路由操作有哪些?等等这些问题,就是本篇要探讨的主要问题 二.vue-router是什么 这里的路由并不是指我们平时所说的硬件路由器, 这里的路由就是SPA(单页应用)的路径管理器 .再通俗的说,vue-router就是WebApp的链接路径管理系统. vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用.

随机推荐