VueRouter模拟实现与源码解读

1、Vue.use( )源码

源码位置:vue/src/core/global-api/use.js

export function initUse (Vue: GlobalAPI) {
   
    //use方法的参数接收的是一个插件,该插件的类型可以是一个函数,也可以是一个对象
  Vue.use = function (plugin: Function | Object) {
   
      //_installedPlugins数组中存放已经安装的插件。
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    //判断一下传递过来的插件是否在installedPlugins中存在,如果存在,则直接返回
    if (installedPlugins.indexOf(plugin) > -1) {
   
      return this
    }

    // additional parameters
      //将arguments转换成数组,并且将数组中的第一项去除。
    const args = toArray(arguments, 1)
    //把this(也就是Vue,这里是通过Vue.use来调用的)插入到数组中的第一个元素的位置。
    args.unshift(this)
      //这时plugin是一个对象,看一下是否有install这个函数。
    if (typeof plugin.install === 'function') {
   
        //如果有install这个函数,直接调用
        //这里通过apply将args数组中的每一项展开传递给install这个函数。
        // plugin.install(args[0],args[1])
        //而args[0],就是上面我们所插入的Vue.这一点与我们前面在模拟install方法的时候是一样的。
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
   
        //如果plugin是一个函数,则直接通过apply去调用
      plugin.apply(null, args)
    }
      //将插件存储到installedPlugins数组中。
    installedPlugins.push(plugin)
    return this
  }
}

2、install方法分析

我们先来看一下vue-router的目录结构

在这里插入图片描述

我们先来核心的文件。

components目录下面,有两个文件。分别为link.jsview.js文件。

link.js文件创建RouterLink组件

view.js文件创建RouterView组件。

history目录下的文件是记录路由的历史记录(hash.js文件是关于hash模式,html5.js关于html5的方式,base.js公共的内容,abstract.js是在服务端渲染中实现的路由历史记录)。

index.js文件是用来创建VueRouter

install.js文件是关于install方法

我们自己模拟的VueRouter也实现上面的目录结构。

下面先来在index.js文件中实现基本代码。

export default class VueRouter {
   
  //在创建VueRouter对象的时候,会传递选项
  constructor(options) {
   
    //获取routes选项,该选项中定义路由规则
    this._options = options.routes || [];
  }
  // 注册路由变化的事件。该方法的参数是一个Vue实例,后期完善
  init(Vue) {
   }
}

下面实现install.js基本代码(通过查看源代码来实现)

export let _Vue = null; //将其导出,在其它文件中也可以使用Vue实例,而不需要单独的引入Vue的js文件
export default function install(Vue) {
   
  //获取Vue构造函数
  _Vue = Vue;
  _Vue.mixin({
   
    //通过混入以后,所有的Vue实例中都会有beforeCreate方法
    beforeCreate() {
   
      //判断是否为Vue的实例,如果条件成立为Vue的实例,否则为其它对应的组件(因为在创建Vue实例的时候会传递选项)
      if (this.$options.router) {
   
        //通过查看源码发现,Vue的实例会挂在到当前的私有属性_routerRoot属性上
        this._routerRoot = this;

    
        this._router = this.$options.router;
        //调用index.js文件中定义的init方法
        this._router.init(this);
      } else {
   
      
        this._routerRoot = this.$parent && this.$parent._routerRoot;
      }
    },
  });
}

3、组件创建测试

下面需要将install方法挂载到VueRouter上。

import install from "./install";
export default class VueRouter {
   
  //在创建VueRouter对象的时候,会传递选项
  constructor(options) {
   
    //获取routes选项,该选项中定义路由规则
    this._routes = options.routes || [];
  }
  // 注册路由变化的事件。
  init(Vue) {
   }
}
//将install方法挂载到VueRouter上
VueRouter.install = install;

下面,我们可以简单实现一下Router-link组件与Router-view组件,来做一个简单的测试。(接下来讲解如下内容)

components目录下的view.js文件。

export default {
   
  render(h) {
   
    return h("div", "router-view");
  },
};

以上是Router-View组件的基本功能,后面在继续完善。

link.js文件的实现如下:

export default {
   
  props: {
   
    to: {
   
      type: String,
      required: true,
    },
  },
  render(h) {
   
      //通过插槽获取`a`标签内的文本。
    return h("a", {
    domProps: {
    href: "#" + this.to } }, [this.$slots.default]);
  },
};

install.js文件中,导入上面的组件进行测试。

import View from "./components/view";
import Link from "./components/link";
export let _Vue = null; //将其导出,在其它文件中也可以使用Vue实例,而不需要单独的引入Vue的js文件
export default function install(Vue) {
   
  //获取Vue构造函数
  _Vue = Vue;
  _Vue.mixin({
   
    //通过混入以后,所有的Vue实例中都会有beforeCreate方法
    beforeCreate() {
   
      //判断是否为Vue的实例,如果条件成立为Vue的实例,否则为其它对应的组件(因为在创建Vue实例的时候会传递选项)
      if (this.$options.router
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Seric.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值