Vue. Use source code analysis

import { toArray } from '.. /util/index'

export function initUse (Vue: GlobalAPI) {
  Vue.use = function (plugin: Function | Object) {
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }

    // additional parameters
    const args = toArray(arguments.1)
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this}}Copy the code
  • Point 1: Avoid repeated installation, first there will be a check whether it has been installed, if so, directly back
  • Point 2:

If the plug-in has the Install method, the install method is called directly

If the plug-in itself is a method, run it directly

Keep a record of installed plug-ins to avoid repeated installation

Two, vUE package plug-in common methods

1. Add global methods or attributes, such asvue-custom-element

MyPlugin.install = function (Vue, options) { 
// The first method. Add global methods or properties
    Vue.myGlobalMethod = function () { 
    / / logic...}}Copy the code

Registration method

import registerCustomElement from './utils/registerCustomElement';
import { getProps, convertAttributeValue } from './utils/props';

function install(Vue) {
  Vue.customElement = function vueCustomElement(tag, componentDefinition, options = {}) {
    const isAsyncComponent = typeof componentDefinition === 'function';
    const optionsProps = isAsyncComponent && { props: options.props || [] };
    const props = getProps(isAsyncComponent ? optionsProps : componentDefinition);
    // register Custom Element
    const CustomElement = registerCustomElement(tag, {
      // Related operations
    });

    return CustomElement;
  };
}

export default install;

if (typeof window! = ='undefined' && window.Vue) {
  window.Vue.use(install);
  if (install.installed) {
    install.installed = false; }}Copy the code

Method of use

  Vue.customElement('widget-vue', {
  props: [
    'prop1'.'prop2'.'prop3'].data: {
    message: 'Hello Vue! '
  },
  template: '

{{ message }}, {{ prop1 }}, {{prop2}}, {{prop3}}

'
}); Copy the code
<widget-vue prop1="1" prop2="string" prop3="true"></widget-vue>
Copy the code

2. Add global resources: directives/filters/transitions, etc.vue-touch

vueTouch.install = function (Vue) {

  Vue.directive('touch', {

    isFn: true.acceptStatement: true.priority: Vue.directive('on').priority,

    bind: function () {
      // The binding operation
    },

    update: function (fn) {
      // Update operations
    },

    unbind: function () {
      // Unbind}})}Copy the code

3. Add some component options via mixin methods, such asvue-router

Plug-in internal definition:

  Vue.mixin({
    beforeCreate () {
      if (isDef(this.$options.router)) {
        this._routerRoot = this
        this._router = this.$options.router
        this._router.init(this)
        Vue.util.defineReactive(this.'_route'.this._router.history.current)
      } else {
        this._routerRoot = (this.$parent && this.$parent._routerRoot) || this
      }
      registerInstance(this.this)
    },
    destroyed () {
      registerInstance(this)}})Copy the code

External use:

new Vue({
  router,
  render: h= > h(App),
}).$mount('#app')
Copy the code

So each component will execute this._router.init(this) when executing the beforeCreate life cycle.

4. Add Vue instance methods by adding them to VUe.prototype

Vue.prototype.$myMethod = function (methodOptions) 
{ / / logic... }
Copy the code

5. Globally register components, such aselementUI

// The sixth way is to register the componentVue.com Ponent (Component name, component)Copy the code

3. The principle of openness and isolation

Being open to extension means that existing code can be extended to accommodate new requirements or changes

Being closed to changes means that once the class is designed, it can do its work independently without making any changes to the class

Rule suggestions:

1. Open and closed principle is the most important design principle. Liskov substitution principle and composite/polymerization reuse principle provide guarantee for the realization of open and closed principle.

2. Reconstruction can be carried out through Template Method mode and Strategy mode to achieve a design idea that is closed to modification and open to expansion.

3. Encapsulating changes is an important means to realize the open and closed principle. For the frequently changing state, it is generally encapsulated as an abstraction, such as the IBankProcess interface in banking business.

4. Refuse to abuse abstraction and only abstract the parts that change frequently. This experience can be gained by learning and applying design patterns.

Iv. Principles of plug-in development

  • Plug-in parameters should be kept to a minimum and focused on user concerns
  • The implementation of a plug-in or component should be based on usage scenarios
  • Developing a component or plug-in should maintain the open and closed principles of software engineering
  • A good plug-in or component is not achieved overnight, and often needs to find problems in the later use process, to improve
    • A component or plug-in must be well documented, and not everyone who uses it is concerned with its internal implementation. They are more concerned with getting started quickly

Five, core code

Toast the plugin

It can only be called functionally

import Toast from './component'
import { iconsMap, titleMap } from './config'
const ToastPlugin = {
  install (Vue, options = {}) {
    const ToastConstructor = Vue.extend(Toast)
    Vue.prototype.$toast = toast

    function buildProps (args) {
      let props = {}
      // Configuration item operation
      return props
    }

    function toast () {
      if (!arguments[0]) return
      const propsData = buildProps(arguments)
      const instance = new ToastConstructor({ propsData })
      document.body.appendChild(instance.$mount().$el)
    }
  }
}

export default ToastPlugin
Copy the code

Text input includes emoticons

import Emoji from './App.vue'
const components = [
  Emoji
]

const install = function (Vue, opts = {}) {
  components.map(component= >{ Vue.component(component.name, component); })}/* Supports the use of tags to introduce */
if (typeof window! = ='undefined' && window.Vue) {
  install(window.Vue);
}
export default {
  install,
  Emoji
}
Copy the code

Vue. use When installing the plug-in, the install method is executed directly, that is, it is registered globally and can be called via tags (elementUI).