xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

vue.use 实现原理剖析 All In One

vue.use 实现原理剖析 All In One

插件通常用来为 Vue 添加全局功能。

插件的功能范围没有严格的限制, 一般有下面几种:

  1. 添加全局方法或者 property。如:vue-custom-element

  2. 添加全局资源:指令/过滤器/过渡等。如 vue-touch

  3. 通过全局混入来添加一些组件选项。如 vue-router

  4. 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。

  5. 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router

源码解读

/**
 * 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
}

util/index => shared/util.js

https://github.com/vuejs/vue/blob/master/src/shared/util.js

/* @flow */

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 转换成 apply 支持的参数数组形式
    const args = toArray(arguments, 1)
   // 从数组前面插入 this
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      // plugin 是个对象,而且有 install 方法
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      // plugin 本身是个方法
      plugin.apply(null, args)
    }
    // 收集 plugin
    installedPlugins.push(plugin)
    return this
  }
}

https://github.com/vuejs/vue/blob/dev/src/core/global-api/use.js

https://github.com/vuejs/vue/blob/master/src/core/global-api/use.js

Vue 2.x

全局方法 Vue.use() 使用插件, 必须放在调用 new Vue() 前。


Vue.use(MyPlugin);
// 调用插件的 install 方法 `MyPlugin.install(Vue)`;

// Vue.use(MyPlugin, { someOption: true });

new Vue({
  // ...
});

// 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
var Vue = require('vue');

var VueRouter = require('vue-router');
// 手动调用插件
Vue.use(VueRouter);

// 检查到全局变量 Vue 后才调用插件 ✅
if(globalThis.Vue) {
    Vue.use(VueRouter);
}

if(globalThis.Vue) {
    console.log('globalThis.Vue =', typeof globalThis.Vue);
}
// globalThis.Vue = function

自定义插件

MyPlugin.install = function (Vue, options) {
  // 1. 添加全局方法或 property
  Vue.myGlobalMethod = function () {
    // ...
  };
  // 2. 添加全局资源 (指令/过滤器/过渡)
  Vue.directive('my-directive', {
    bind (el, binding, vnode, oldVnode) {
      // ...
    },
    //...
  });
  Vue.directive('my-filter', function (value) {
    if (!value || typoef value !== 'string') {
      return '';
    }
    return `${value[0].toUpperCase()}${value.slice(1)}`;
    // value = 
    // return value.charAt(0).toUpperCase() + value.slice(1);
  });
  // 3. 全局混入/全局注入一些组件选项
  Vue.mixin({
    created: function () {
      // ...
      console.log('created', mixin);
    },
    //...
    data () {
       isLoading: false,
       isDebugging: false,
    },
    methods: {
       log(value) {
          // 打印组建名称
          const componetName = `✅👍🚀 ${this.name}` || '❌👎💩 Anonymous Component';
          console.log(`${componetName}'s value =`, value);
       },
    },
  });
  // 4. 添加实例方法
  Vue.prototype.$myMethod = function (methodOptions) {
    // ...
  };
  Vue.prototype.monitor = function (options = {}) {
    // 监控 SDK
    console.log('上报数据', options);
  };
}

https://cn.vuejs.org/v2/api/#Vue-use

https://cn.vuejs.org/v2/guide/plugins.html

Vue 3.x


https://v3.cn.vuejs.org/guide/plugins.html

demo

refs



©xgqfrms 2012-2020

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-03-18 11:17  xgqfrms  阅读(57)  评论(3编辑  收藏  举报