Vue原理:全局API-Vue.use实现

这是我参与11月更文挑战的第26天,活动详情查看:2021最后一次更文挑战

Vue中为开发者提供了大量的全局API,例如Vue.useVue.extendVue.nextTick等,因为这些全局API的存在,方便在开发中使用和扩展一些能力

比如我们想要使用一个插件时,需要使用Vue.use(plugin)进行全局能力的注册,可以为Vue添加全局的方法或者属性等

initGlobalAPI

Vue中对于全局API是如何处理的呢?

在初始化入口提供一个initGlobalAPI函数,调用initGlobalAPI(Vue)进行全局API注册

初始化initGlobalAPI函数

export function initGlobalAPI(Vue) {
}
复制代码

在函数内部会将全部的全局API进行初始化,大致如下


const ASSET_TYPES = ["component", "directive", "filter"];

export function initGlobalAPI(Vue) {
  Vue.set = set;
  Vue.delete = del;
  Vue.nextTick = nextTick;
	
  // 整合所有的全局相关的内容
  Vue.options = Object.create(null);
  ASSET_TYPES.forEach((type) => {
    Vue.options[type + "s"] = Object.create(null);
  });

  initUse(Vue);
  initMixin(Vue);
  initExtend(Vue);
  initAssetRegisters(Vue);
}
复制代码

Vue.use

当我们想要在Vue项目中使用Vuex时,就需要使用Vue.use进行安装Vuex

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
复制代码

在整个Vue项目中每个组件实例都可以通过this.$stroe来进行数据管理

Vue.use实现:在initGlobalAPI函数中调用initUse函数进行全局API注册

export function initUse (Vue) {
  // 在Vue上添加use函数
  Vue.use = function (plugin) {
    // todo...
  }
}
复制代码

Vue规定所有的插件若是一个对象,则其必须提供一个install函数。若插件是一个函数,那么这个插件就会被当作install函数。install调用时会将Vue作为第一个参数传入


/**
 * 将类数组转换为数组
 */
const toArray = (list, start) => {
  start = start || 0;
  let i = list.length - start;
  const ret = new Array(i);
  // 循环类数组,将其值赋值给数组
  while (i--) {
    ret[i] = list[i + start];
  }

  // 返回生成的数组
  return ret;
};

// 缓存已加载的插件
const _installedPlugins = [];

Vue.use = function (plugin) {
  // 已经注册过的全部插件
  const installedPlugins =
    this._installedPlugins || (this._installedPlugins = []);
  // 若是插件注册过,则直接返回
  if (installedPlugins.indexOf(plugin) > -1) {
    return this;
  }

  // 将第一个参数之后的数据转换为数组,一般是插件的配置项信息
  const args = toArray(arguments, 1);
  // 将Vue作为插件执行时第一个参数传入
  args.unshift(this);

  // 如果插件是一个对象且具有install函数
  if (typeof plugin.install === "function") {
    plugin.install.apply(plugin, args);
  } else if (typeof plugin === "function") {
    // 插件是一个函数,直接将插件作为install函数执行
    plugin.apply(null, args);
  }

  installedPlugins.push(plugin);
  return this;
};
复制代码

おすすめ

転載: juejin.im/post/7034701418787241997