Skip to content

use

javascript
// 安装 Vue.js 插件, install 方法调用时, 会将 Vue 作为参数传入。在第一次调用时,
// 会往 Vue 上挂载_installedPlugins,是一个数组,用于记录已安装的插件,Vue.use 内部
// 第一件事就是判断是否安装了,即 installedPlugins.indexOf(plugin) > -1
// 没有安装的话会将 Vue.use 调用时传入的第一项以外的参数取出,也就是给插件传的参数。
// 另外再将 Vue 添加参数数组最前面,之后判断 plugin.install 是不是函数,如果不是,说明
// 这个插件是对象式插件并且提供了 install 方法,只需要把 install.apply(this, args)
// 否则就判断 plugin 是不是函数,如果是说明是函数式插件,这个函数本身就会被作为
// install 方法,直接 plugin.apply(this, args)。插件安装完成后 installPlugins 中
// 添加 plugin,最后返回 this 用于链式调用。
Vue.use = function (plugin) {
  const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
  
  if (installedPlugins.indexOf(plugin) > -1) { // 防止重复安装
    return this
  }

  // 将第一个参数(插件名)之外的其他参数转化为数组,Vue.use(plugin, arg1, arg2, ...)
  const args = toArray(arguments, 1);
  args.unshift(this); // 最前面添加Vue
  
  if (typeof plugin.install === 'function') {
    // 插件是一个对象,必须提供 install 方法
    plugin.install.apply(plugin, args);
  } else if (typeof plugin === 'function') {
    // 插件是一个函数,它会被作为 install 方法。
    plugin.apply(null, args);
  }
  
  installedPlugins.push(plugin) // 安装完成,添加进数组中
  
  return this // 链式调用
};

function toArray (list, start) {
  start = start || 0;
  let i = list.length - start;
  const res = new Array(i)
  
  while (i--) {
    res[i] = list[i + start];
  }
    
  return res
}