美文网首页
简陋的Vue-Router实现

简陋的Vue-Router实现

作者: CodeYJ | 来源:发表于2020-06-23 09:53 被阅读0次

前言

源码地址

好奇 Vue 与 Vue-Router 是怎么形成关联,怎么去渲染的,就出现了这篇总结的文章。
在使用Vue-Router的过程中都要经过这几个步骤:

  1. Vue-Router 实例化
  2. Vue-Router 的实例通过 Vue.use 形式建立关系
  3. Vue-Router 的实例挂载到 Vue 根实例的 options 里
const router = new VueRouter() // 1
Vue.use(router) // 2
new Vue({router}) // 3

路由变化与组件渲染关联

每当路由变化, Router-View 组件都会重渲染。

关联思考

换个角度思考。先不思考怎样去关联。
问题:先想一下Router-View怎样才能重新渲染?
解决方向:毫无疑问,Router-View是用在Vue框架内,所以第一反应,想到的就是依赖发生变化。
问题:依赖关系如何产生?
解决方向:取个巧,我不直接与Router-View产生依赖关系,我与Router-View所在的组件产生依赖关系。
所以,我们能到下面的简图:

image.png

路由初始化并获取引用

const demo1 = Vue.component("demo1", { template: `<div>demo1</div>` });
const demo2 = Vue.component("demo2", { template: `<div>demo2</div>` });
const demo3 = Vue.component("demo3", { template: `<div>demo3</div>` });

class VueRouter{
  constructor(options){
      this.routers = options.routers;
      this.current = null
      this.comContain=[]
  }
  init(vueCompentInstance){
      this.comContain.push(vueCompentInstance)
  }
}

const router = new VueRouter({ routers: [demo1, demo2,demo3] });

const install = (Vue) => {
  // 在每个组件的指定生命周期内,处理你想处理的事情
  Vue.mixin({
    beforeCreate() {
      this._route = this.$parent
        ? this.$parent.$options.router
        : this.$options.router;
      //获取引用
      this._route.init(this);
      //建立依赖关系
      Vue.util.defineReactive(this, "_route", this._route.current);
    },
  });

  Object.defineProperty(Vue.prototype, "$router", {
    get() {
      return this.$options.router;
    },
  });
};

router.install = install;

Vue.use(router);

路由监控(hash)

// 以hash模式为例子,通过原生事件监控hash变化
class VueRouter{
  constructor(options){
      this.routers = options.routers;
      this.current = null
      this.comContain=[]
   window.addEventListener("hashchange", (el) => {
       const { newURL } = el;
       const target = newURL.split("#");
       // 手动匹配组件
       if(target.length>0){
           const t = target[1]
           if(t==='a'){
               this.update(this.routers[0])
           }else if(t==='b'){
               this.update(this.routers[1])
           }else if(t==='c'){
               this.update(this.routers[2])
           }
        }
    })
  }
  // 初始化
  init(vueCompentInstance){
      this.comContain.push(vueCompentInstance)
  }
  // 刷新依赖
  update(com){
    this.comContain.forEach(route=>{
      route._route=com
    })
  }
}

Router-View

选择了 Vue.compoent 的 functional 模式。

const regView = (Vue) => {
  Vue.component("router-view", {
    functional: true,
    render(createElement, { props, children, parent, data }) {
      const router = (parent.$router && parent.$router.routers) || [];
      const component = parent._route;
      if (!component) {
        return createElement();
      }
      return createElement(component);
    },
  });
};

相关文章

网友评论

      本文标题:简陋的Vue-Router实现

      本文链接:https://www.haomeiwen.com/subject/lzecfktx.html