Vue-Router principle analysis - routing mode and install

  Single Page Application (SPA, Single Page Application) of the entire Web system, by a html file via Ajax and back-end data exchange, through some special means to load different parts of the rendering of the page, without refreshing the whole page so that ,, just use app as greatly enhance the user experience in ecology Vue, Vue's core is the use of plug--Vue-Router to implement routing jump Web interface, so, this paper is to study Vue-Router, understand Vue-Router SPA achieve complete development of specific principles.

Web Route Overview

  First briefly about routing, routing system early Web server mainly back-end implementation, familiar with the front and rear side development friends will know that, in the server, mapped to the appropriate method by routing tables, and perform the appropriate action, such as we would like to request API data, a new page documents:


"/" -> goHtml()

"/api/users" -> queryUsers()

  The client achieve major route there are two ways:

1. 基于Web Url的hash
2. 基于Hishtory API

Based on the hash Web Url

   Url hash value is the parameter value of "#" sign, such as http://www.example.com/index.html#location1the value inside localtion1, mainly has the following characteristics (see Url before the company projects with "#", though a bit strange, but did not think about ye want to come, Khan):

1. Url中#后的内容不会发送到服务器;
2. hash值的改变会保存到浏览器的历史浏览记录中,可通过浏览器的回退按钮查看;
3. hash值是可读写的,可通过window.location.hash获取到hash值,利用onhashchange监听hash值的变化(Vue-Router里的hash模式就是在onhashchange中的回调事件中完成路由到界面的更新渲染)。

Based Hishtory API

  Hash-based model is convenient, but with a # sign, some students will feel a bit ugly it so Url, to Url style and the same request to the back-end server is consistent, you can use the Hishtory API mode. Hishtory API based mainly provided by operating the operation HTML5 browser history API, it can not achieve address refresh update the address bar, for example:

// pushState  state: 用于描述新记录的一些特性。
// 这个参数会被一并添加到历史记录中,以供以后使用。
// 这个参数是开发者根据自己的需要自由给出的。
// pushState作用相当于修改“#”后面的值
window.history.pushState(state, "title", "/userPage");
// 比如浏览器后退
window.addEventListener("popstate", function(e) {
    var state = e.state;
    // do something...
});
// 与pushState相对仅进行Url替换而不产生新的浏览记录的replaceState方法
window.history.replaceState(null, null, "/userPage");

Comparison of two modes

  We simply compare some of the features of these two models:

VS mode hash Hishtory API
Aesthetic appearance Recognized a little ugly, with the # Relative beautiful
compatibility it is good Need browser that supports HTML5
URL error back-end support no Yes

  Therefore, the use of two modes according to the actual needs of the project to set up, then it is the focus of internal Vue-Router for routing is based on these two models! So early we look at the front end of the route of the two modes be considered to make a shot.

View router

   Recall that the first four steps used Vue-Router, and:

import Vue from 'vue';
import VueRouter from 'vue-router'
// 1. 使用Vue-Router插件
Vue.use(VueRouter)
// 2. VueRouter实例化
const router = new VueRouter({
  model: 'history', // 路由模式 hash\history
  routes: [
    {
      name: 'xx',
      path: 'path',
      component: component
    }
  ]
});
// 3. 实例化Vue实例时使用该router路由
new Vue({
  ...
  router,
});

// 4. 通过Vue.$router.push('xx') 或 router-link进行路由跳转

  Then, on successive snoop above four steps in Vue-Router some specific implementation details.

Use plug-Vue-Router

  VueRouter follow the development of norms Vue plug-in by calling Vue internal method Vue.use () to VueRouter (install method is actually a callback VueRouter defined) install carried out, a process completed work VueRouter the mount.

-> vue\src\core\global-api\use.js
Vue.use = function (plugin: Function | Object) {
  ... 
  plugin.install.apply(plugin, args);
  ...
}

  Back VueRouter source code, analyze the flow of execution install process:

import View from './components/view'
import Link from './components/link'

export let _Vue

// install实现
export function install (Vue) {

  // 如果已注册实例,则返回
  if (install.installed && _Vue === Vue) return
  install.installed = true

  _Vue = Vue 

  const isDef = v => v !== undefined

  const registerInstance = (vm, callVal) => {
    // 父虚拟节点
    let i = vm.$options._parentVnode
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal)
    }
  }

  Vue.mixin({
    // 路由钩子函数,在vue执行beforeCreate钩子函数回调时会一起调用,因为beforeCreate是一个数组
    beforeCreate () {
      Vue.$options = options
      if (isDef(this.$options.router)) {
        this._routerRoot = this
        this._router = this.$options.router
        // 调用init
        this._router.init(this)
        // 调用Vue内部util方法使得当前的url实现响应式化
        Vue.util.defineReactive(this, '_route', this._router.history.current)
      } else {
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      // 注册实例
      registerInstance(this, this)
    },
    destroyed () {
      registerInstance(this)
    }
  })
  // 将$router和$route挂载到Vue的原型链上
  Object.defineProperty(Vue.prototype, '$router', {
    get () { return this._routerRoot._router }
  })

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

  // 注册路由视图和路由链接两个组件
  Vue.component('RouterView', View)
  Vue.component('RouterLink', Link)

  // 执行Vue的选项合并策略
  const strats = Vue.config.optionMergeStrategies
  // use the same hook merging strategy for route hooks
  strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created
}

  It can be seen inside the main install do three things:

    1. Vue mixin method is the use of mixed global beforeCreate and destoryed, when it first loads execution beforeCreate, designated _routerRoot for the current Vue instance, and the init initialization Vue-Router's (install the core or init initialization, the little details after introduction), in beforeCreate methods, mainly on the parent components (i.e. the mounted router nodes) for initialization, and sets the current _routerRoot for instance corresponding components in which the gradual route to initialize init Some configurations (such as setting routing mode, etc.), other components such as (router-link, router-view will include _routerRoot router option is set to the parent (ancestor) component in the options parameter), and performing registerInstance method, the the current method is actually a method registerRouteInstance router-view components as defined in the main role is to execute the current rendering work components, as follows:
const registerInstance = (vm, callVal) => {
    // 父虚拟节点
    let i = vm.$options._parentVnode
    if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {
      i(vm, callVal)
    }
  }

  This is equivalent to the definition of mixed, as each component during the specific execution example of the life cycle and callbacks beforeCreate destoryed two hook function, action is performed such Destroyed after route switching, in fact, a role is to appear router Clear -view components in the rendered content.

    1. The $ and $ route Router prototype chain Vue mount can be made by using this $ router and this $ route..;
    1. Register router-link and router-view of the two components to the Vue.

to sum up

  Because hope not too much space, otherwise looks more difficult, so this article first wrote here, for examples and specific use of the principle involved discuss later in the article. In this make a summary of this article:

  • It introduces the front-end routing, as well as to achieve front-end routing of two modes URL hash and history API and both do a comparison;
  • It describes how to install method is to use Vue-Router Vue assembly is actually inside the callback Vue-Router internally defined;
  • Some of the key job functions install method:
    • BeforeCreate destoryed mixed and methods;
    • Global mounts $ router and $ route;
    • Register router-link and router-view two components.
      Also, welcome to my git can learn from each other and star.

Guess you like

Origin www.cnblogs.com/boykait/p/11106437.html