vue源码阅读之Vue.use()做了什么?

222 阅读2分钟

引文

在vue开发过程中,经常会用到Vue.use,例如Vue.use(ElementUI), Vue.use(VueRouter) 等等,遇到要封装一个公共组件或插件的需求,也会用到Vue.use去注册插件,那么use究竟做了什么,今天来探索下。

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

// toArray 将伪数组转为数组
export function toArray (list: any, start?: number): Array<any> {
  start = start || 0
  let i = list.length - start
  const ret: Array<any> = new Array(i)
  while (i--) {
    ret[i] = list[i + start]
  }
  return ret
}
import { toArray } from '../util/index'

export function initUse (Vue: GlobalAPI) {
  // 声明 Vue.use
  Vue.use = function (plugin: Function | Object) {
    // 已注册插件列表
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    // 判断插件是否已注册 已注册返回
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }

    // 附加参数处理
    const args = toArray(arguments, 1)
    // 附加参数添加this上下文
    args.unshift(this)
    // 判断有无install方法
    if (typeof plugin.install === 'function') {
      // 调用install方法
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      // 调用本身 指向null
      plugin.apply(null, args)
    }
    // 插件列表添加
    installedPlugins.push(plugin)
    return this
  }
}

综上所述,得出以下结论

  1. 在Vue.use的时候,参数接受方法或者对象,先判断插件是否已注册,已注册返回。
  2. 处理附加参数(Vue.use(plugin, params1, .... ),获取到[params1, ....]),将this添加到参数首位
  3. 判断插件有无install方法,有的话执行插件install方法,没有的话执行插件本身

插件俩种形式对比

// main.js
import Vue from 'vue';

// 对象 含有install方法
const plugin1 = {
  name: '萌新',
  install(x) {
    console.log('参数1', x);
    console.log('参数2', [...arguments]);
    console.log(this);  // 对象 含有install方法源码 plugin.install.apply(plugin, args)
  }
}

// 函数 没有install方法
const plugin2 = function(x) {
  console.log('参数1', x);
  console.log('参数2', [...arguments]);
  console.log(this); // 函数 没有install方法源码 plugin.apply(null, args)
}

Vue.use(plugin1, '小菜菜', '菜鸡');
Vue.use(plugin2, '摸鱼', '大佬');

综上所述,可以得出以下结论

含有install方法的对象的this指向插件本身,所以可拓展性更高一些,function类型的插件this指向null,相对来说拓展性低一点。

总结

Vue.use()用来注册插件,接受函数或有install方法对象,首先会判断插件注册与否,已注册返回,未注册处理剩余参数,参数处理后判断插件是否含有install方法,有的话执行install方法this指向插件本身,没有则执行函数本身,this指向null。