The use method is provided in Vue to install plug-ins, so what is the principle of Vue plug-ins?

A, Vue. Use

The official description of the use method is shown below:

That is, the vue.use () method takes as an argument either a function or an object that provides the install method (the install method must be provided), and if the argument passed is a function, the function is treated as the install method.

Documents: cn.vuejs.org/v2/api/#Vue…

Vue2.6.11 use:

InitUse adds a static method to Vue. The use method takes a plugin, determines whether the parameter is an object or a function, and executes the logic.

Take vex3.6.2 version as an example, directly look at the source code:

It exposes an install method that validates what we learned earlier: vue.use (vuex) uses this install method to install the plug-in.

So what does the vuex install function do?

You can see that it calls applyMixin and passes the Vue

The applyMixin function is as follows:

In the vue2. X version, vuex extends the functionality directly with vuue. Mixin, which takes advantage of features that the mixin hook will call before the component hook, and adds a beforeCreate hook to the application, where the vuex plug-in is initialized.

Second, the mixin

I have to say something about mixins

What: Mixin is a JS design pattern that can be easily inherited by subclasses for function reuse. This design pattern is also applied in Vue. Mixin can be used to distribute reusable logic.

Why: When multiple components have similar data and methods, can you extract the data and methods and inject logic into the components that need the data and methods by mixing them? This will save us a lot of code and is the reason Vue designed mixins

How: There are two ways to use it: global mixing and local mixing. For details, please refer to cn.vuejs.org/v2/guide/mi…

Note: Try to avoid using global mix, for it will affect all instances of the vue (sometimes puzzling feature is messed up all don’t know what happened, is very difficult to screen), if the component with mixins has the property of the same name, will be option to merge, in addition to the life cycle, all the other attributes will be covered by its own component attributes, Similar to inheritance, if a subclass has the property or method itself, it is no longer looking up the stereotype chain, the lifecycle is merged into an array, and the blended hooks are called before the component’s hooks.

The source code for mixins is very simple, just call mergeOptions to mergeOptions

For mergeOptions function parsing, read this article: juejin.cn/post/684490…

The principle of other plug-in development is similar, the official documentation is as follows:

Implement a plugin yourself

Now let’s implement a prompt plug-in that can be called through this.$notify() and pass in a custom template

Analysis requirements:

  • To implement a Vue plug-in, we first need to provide an object according to the vue. use convention. This object must have the install function, or provide a function
  • Calling this means that this method needs to hang on Vue’s prototype object, so we need to add a $notify method to Vue’s prototype
  • The fact that custom templates can be passed in means that we need to call the API to compile the incoming template

Now let’s create a vue project, create a plugin directory under SRC, then create a notify directory, and create index.js and notify.vue

You might be wondering why create a notify. vue

Based on our previous analysis, we know that the basic structure of a plug-in is as follows:

// index.js
function notify() { 
    function install(Vue) {
    
    } 
    
    return { install }; 
} 

export default notify();
Copy the code

Then we need to add notify methods to the Vue prototype object, so we can use this.notify, so we can use this.notify, so we can call this.notify()

// index.js function install(Vue) { Vue.prototype.$notify = notifyInit; } function notifyInit(options) {console.log(' call successful ')}Copy the code

The basic functionality of a plugin is now complete, and we can use it via vue.use, in main.js:

// main.js 
import notify from './plugins/notify/index' 
Vue.use(notify);
Copy the code

Then we verify the function in app.vue and call this.notify() when clicked.

<template> <div id="app"> < button@click ="handleShow"> display </button> </div> </template> <script> export default {name: 'App', methods: { handleShow() { this.$notify() } } } </script>Copy the code

This is working fine up to this point, and we’ve implemented calling this.notify() to prompt

Then we need to implement passing in the template and displaying it, so the question is, passing in the template is easy to understand, how do you compile the template and displaying it?

To do this, Vue provides us with the $mount API, which is officially described as follows:

Documents: cn.vuejs.org/v2/api/#vm-…

Now that you can manually mount an instance, you can create a Vue component, create the DOM, js, and style in the component, and finally insert the mounted element into the document when $notify is called. That’s what notify. Vue does

Notify. Vue We first create a simple structure, the code is as follows:

<template>
  <div class="notify" v-if="isShow">
    <div id="content"></div>
  </div>
</template>

<script>
export default {
  name: "notify",
};
</script>

<style>
.notify #content {
  position: fixed;
  bottom: 10px;
  right: 10px;
  z-index: 999;
  width: 200px;
  height: 150px;
  border-radius: 5px;
  border: 1px solid #e5e5e5;
}
</style>
Copy the code

In index.js, we need to import this component, which is implemented through the Vue injected in the install method, in the following steps:

  • Call vue.extend to extend Notify for the single-file component
  • Get the Notify component instance
  • Call $mount to mount the instance
  • Get el and insert el and insert EL into the document

Note: the $EL option is not accessible until the instance is mounted, as stated clearly in the official documentation

Documents: cn.vuejs.org/v2/api/#el

The code is as follows:

import Notify from "./Notify.vue"; function notify() { function install(Vue) { elementInit(Vue); Vue.prototype.$notify = notifyInit; } function elementInit(Vue) {const ClassNotify = Vue. Extend (Vue); // Get component instance const instance = new ClassNotify(); // Add the el option instance.$mount(); // get el const el = instance.$el; / / insert el document. The body. The appendChild (el); } function notifyInit(options) {console.log(' call successful ')} return {install,}; } export default notify();Copy the code

Now that we have successfully inserted the component into the body, you should not be surprised to find the box shown in the image below in the lower right corner of the page

The next step is to implement passing in the template. Vue also provides v-HTML instructions to insert the template

Documents: cn.vuejs.org/v2/api/#v-h…

All we need to do is pass the received configuration parameters to the Notify component when we call this.notify(), which will be rendered by the V-HTML directive

If we access the Notify instance directly in the notifyInit function, we obviously cannot. This refers to the component that currently calls $Notify, which in this case is app.vue

By virtue of the $mount call returning the VM (the instance itself), we can save the Notify component and access it in the notifyInit function

import Notify from "./Notify.vue"; function notify() { let NotifyComponent; function install(Vue) { elementInit(Vue); Vue.prototype.$notify = notifyInit; } function elementInit(Vue) {const ClassNotify = Vue. Extend (Vue); // Get component instance const instance = new ClassNotify(); // Mount the component, add the EL option, and assign the VM to NotifyComponent NotifyComponent = instance.$mount(); // get el const el = instance.$el; / / insert el document. The body. The appendChild (el); } function notifyInit(options) {// Call notify and pass through the configuration parameters to notifyComponent.notify (options); } return { install, }; } export default notify();Copy the code

Then we just need to add this method to notify. vue to receive the parameters

<template> <div class="notify" v-if="isShow"> <div id="content" v-html="content"></div> </div> </template> <script> Export default {name: "notify", data() {return {isShow: false, content: "zhang Three ",}; }, methods: { notify(options) { this.isShow = true; SetTimeout (() => {this.isShow = false; }, 2000) // use the default options && & options.content && (this.content = options.content); ,}}}; </script> <style> .notify #content { position: fixed; bottom: 10px; right: 10px; z-index: 999; width: 200px; height: 150px; border-radius: 5px; border: 1px solid #e5e5e5; } </style>Copy the code

At this point we pass a template in app.vue

The effect of the operation on the page is as follows and disappears after two seconds