当前位置:   article > 正文

知道Vue中router实现的底层原理吗?_vue-router4.0 源码 是如何实现组件切换的

vue-router4.0 源码 是如何实现组件切换的

前言

在我们了解router的实现原理之前,我们先来聊聊vue的路由跳转到底是怎样的吧!

首先,我们知道vue创建的项目其实是一个单页应用。在我们对vue项目进行打包以后,我们所有的代码都会被成一份HTML和一份JS,那我们创建的那么多.vue文件是如何实现通信的呢?

这时我们今天的主角就登场啦,vue-router就是vue官方定义的路由插件,其作用有如下两点:

  • 路由用户设定访问路径的,将路径和组件映射起来。
  • 在vue-router的单页面应用中,页面的路径的改变就是组件的切换

实现一个router

vue官方版router

首先,我们先来看看官方版router,官方版router的实现步骤有五步。我们先来分析分析五步都在干什么。

1:第一步我们在我们的router文件夹下的index.js文件中引入了‘vue-router’插件,将其引入到我们的项目中。

2:第二步我们就要在我们的Vue实例对象中,use掉我们引入的插件,使我们可以在这个实例对象中可以使用VueRouter。

  1. 第三步我们在index.js定义了routes数组给用户来定义其要路由跳转的路径和对路径进行重定向,如上图,第一个对象就是对路由进行重定向,第二个对象就是定义路由跳转的路径。

4.第四步我们就要是new出我们的路由实例对象,选择跳转模式和根路径,同时把我们定义的routes数组给到路由实例对象,再将其抛出,之后我们就可以在main.js中引入引入我们抛出的路由对象了。

5.第五步是最重要的一步,我们要调用router对象中内置的router-link和router-view组件,让其可以在页面中显示出来。这样我们就可以肆无忌惮的跳转页面了。

自己实现一个VueRouter

在我们看完官方版路由后,我们就该疑惑了,在我们引入的这个vue-router组件中,他是怎样让我们可以如此轻松的实现路由跳转的呢?

这时我们就要提出疑惑了,VueRouter这个构造函数中到底创建了什么方法,可以让我们将模式,根路径,跳转路径三个参数传递进去就可以帮我们实现路由跳转的呢?

在官方版VueRouter构造函数中,我们可以看出我们需要处理的由三个东西,第一个就是处理路由跳转的模式(mode),第二个就要处理的就是路由跳转的路径(routes),第三个就要处理路由的根路径和跳转组件。

VueRouter构造函数的实现

下面我们来自己创建VueRouter构造函数,同时我们再来分析分析他的实现原理。

  1. class HistoryRoute { // 保存当前路径状态
  2.     constructor() {
  3.         this.current = null // 用来记录当前路由的路径的变量
  4.     }
  5. }
  6. class VueRouter {
  7.     constructor(options) {
  8.         this.mode = options.mode || 'hash' // 用来记录路由模式的边疆
  9.         this.routes = options.routes // 跳转路径数组
  10.         this.routesMap = this.createMap(this.routes) // 路径对象
  11.         this.history = new HistoryRoute()
  12.         this.init()
  13.     }
  14.     createMap(routes) { // 当前的路由对象
  15.         return routes.reduce((pre, current) => {
  16.             pre[current.path] = current.component  // '/' : Home, '/about' : About
  17.             return pre
  18.         },{})
  19.     }
  20.     init() {
  21.         if(this.mode == 'hash') { // 根据路由跳转的方式,改变路由的实例对象
  22.             location.hash ? '' : location.hash = '/'
  23.             window.addEventListener('load', () => {
  24.                 this.history.current = location.hash.slice(1)
  25.             })
  26.             window.addEventListener('hashchange', () => {
  27.                 this.history.current = location.hash.slice(1)
  28.             })
  29.         }else {
  30.             location.pathname ? '' : location.pathname = '/'
  31.             window.addEventListener('load', () => {
  32.                 this.history.current = location.pathname
  33.             })
  34.             window.addEventListener('popstate', () => {
  35.                 this.history.current = location.pathname
  36.             })
  37.         }
  38.     }
  39. }

在Vue实例对象中混入Vue-Router

  1. let Vue = null  // vue 的实例对象
  2. VueRouter.install = function (params) { // 在VueRouter实例对象的原型上挂上install方法
  3.     Vue = params
  4.     // console.log(Vue);
  5.     Vue.mixin({  //将在其他地方写的api方法混入vue实例对象中
  6.         beforeCreate() {
  7.             if(this.$options && this.$options.router) { // 根组件
  8.                 this._root =this
  9.                 this._router = this.$options.router
  10.                 Vue.util.defineReactive(this, 'xxx', this._router.history)
  11.             }else{ //子组件
  12.                 this._root = this.$parent  && this.$parent._root
  13.             }
  14.             Object.defineProperty(this, '$router', {
  15.                 get () {
  16.                     return this._root.router
  17.                 }
  18.             })
  19.             Object.defineProperty(this, '$route', {
  20.                 get () {
  21.                     return this._root.router.history.current
  22.                 }
  23.             })
  24.         }
  25.     })
  26.     Vue.component('router-link', { // 自带的组件注册  声明全局组件
  27.         props:{
  28.             to: String
  29.         },
  30.         render(h) {
  31.             let mode = this._self._root._router.mode
  32.             let to = mode === 'hash' ? '#'+this.to : this.to
  33.             return h('a', {attrs:{href:to }}, this.$slots.default)
  34.         }
  35.     })
  36.     Vue.component('router-view', {
  37.         render(h) {
  38.             let current = this._self._root._router.history.current // 当前路由地址 '/about'
  39.             let routeMap = this._self._root._router.routesMap  // 所有路由对象
  40.             return h(routeMap[current])
  41.         }
  42.     })
  43. }
  44. export default VueRouter

这样我们直接调用我们自己的MyRouter函数,实现路由跳转,下面我们来看看效果:

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/430400
推荐阅读
相关标签
  

闽ICP备14008679号