Vue2.6.14源码学习:use做了什么?

194 阅读1分钟

Vue.use( plugin )

  • 参数
  • {Object | Function} plugin

安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。

该方法需要在调用 new Vue() 之前被调用。

当 install 方法被同一个插件多次调用,插件将只会被安装一次。

// 源码路径:src/core/global-api/use.js
/* @flow */

/*
  toArray:将类数组对象转换为真正的数组。
*/
import { toArray } from "../util/index";

export function initUse(Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
    // 拿到已安装的插件或等于一个空数组
    const installedPlugins =
      this._installedPlugins || (this._installedPlugins = []);

    /*
      判断 plugin 是否已经存在
      这也就是为什么插件多次调用只会被安装一次
    */
    if (installedPlugins.indexOf(plugin) > -1) {
      return this;
    }

    /*
      additional parameters 附加参数
      

      arguments 是一个类数组对象: Object { 0: 1, 1: 2, 2: 3, length:3 }  <- 长这样
      经过 toArray 转换会变成一个真正的数组(toArray方法可以看下面)
    */
    const args = toArray(arguments, 1);

    // 向数组头部添加this,保证函数的第一个参数是Vue
    args.unshift(this);

    // 判断 plugin 要么提供一个install函数或者自身就是一个函数
    if (typeof plugin.install === "function") {
      plugin.install.apply(plugin, args);
    } else if (typeof plugin === "function") {
      plugin.apply(null, args);
    }

    // 添加到已安装的插件数组中
    installedPlugins.push(plugin);
    return this;
  };
}

toArray()

/**
 * Convert an Array-like object to a real Array.
 *
 * 将类数组对象转换为真正的数组。
 */
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;
}

// 扩展:es6 更简单

示例

// 本身是一个函数
const plugin1 = (Vue) => {
  Vue.prototype.Element = "饿了么ui";
};

// 本身是一个对象,需要提供一个install方法才会生效
const plugin2 = {
  install: (Vue) => {
    Vue.prototype.elementPlus = "elementPlus";
  },
};

// 多次调用,插件将只会被安装一次。
Vue.use(plugin1);
Vue.use(plugin1);
Vue.use(plugin1);
Vue.use(plugin2);
const app = new Vue({
  data() {
    return {
      count: 0,
    };
  },
}).$mount("#app");

总结

Vue.use会优先拿到已安装的插件,如果没有会直接等于一个空数组,然后再判断该插件是否已被注册,来防止重复注册,然后会将arguments类数组对象转换成一个真正的数组并且向头部添加Vue,最后就是判断插件要么本身是一个函数要么是一个对象并且提供install方法