Vue defines some API and then places it on Vue objects for global use in Vue projects

Vue.extend

Vue.extend takes options for a component and returns a constructor to generate the new component. What are the properties of options? Think about the Vue components we write in our daily life. Templates, data, methods, lifecycle functions, etc.

Demo can view the Vue document, the following is the source paste.

function initExtend (Vue) {
    /** * Each instance constructor, including Vue, has a unique * cid. This enables us to create wrapped "child * constructors" for prototypal inheritance and cache them. * /
    Vue.cid = 0;
    var cid = 1;

    /** * Class inheritance */
    Vue.extend = function (extendOptions) {
      extendOptions = extendOptions || {};
      var Super = this;
      var SuperId = Super.cid;
      var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {});
      if (cachedCtors[SuperId]) {
        return cachedCtors[SuperId]
      }

      var name = extendOptions.name || Super.options.name;
      if (name) {
        validateComponentName(name);
      }

      var Sub = function VueComponent (options) {
        this._init(options);
      };
      Sub.prototype = Object.create(Super.prototype);
      Sub.prototype.constructor = Sub;
      Sub.cid = cid++;
      Sub.options = mergeOptions(
        Super.options,
        extendOptions
      );
      Sub['super'] = Super;

      // For props and computed properties, we define the proxy getters on
      // the Vue instances at extension time, on the extended prototype. This
      // avoids Object.defineProperty calls for each instance created.
      if (Sub.options.props) {
        initProps$1(Sub);
      }
      if (Sub.options.computed) {
        initComputed$1(Sub);
      }

      // allow further extension/mixin/plugin usage
      Sub.extend = Super.extend;
      Sub.mixin = Super.mixin;
      Sub.use = Super.use;

      // create asset registers, so extended classes
      // can have their private assets too.
      ASSET_TYPES.forEach(function (type) {
        Sub[type] = Super[type];
      });
      // enable recursive self-lookup
      if (name) {
        Sub.options.components[name] = Sub;
      }

      // keep a reference to the super options at extension time.
      // later at instantiation we can check if Super's options have
      // been updated.
      Sub.superOptions = Super.options;
      Sub.extendOptions = extendOptions;
      Sub.sealedOptions = extend({}, Sub.options);

      // cache constructor
      cachedCtors[SuperId] = Sub;
      return Sub
    };
  }
Copy the code

Extend. Cid = 0, the SuperId in the following code does not change, and the variable cid indicates that the component ID is placed in the constructor. The new component keeps its ID unique by incrementing. Vue. Extend: the extendOptions parameter is the component options passed in. For convenience we call the component options and execute the function Super equals this. The literal meaning and the following operation, as you can see, is that if the constructor is cached, it is returned directly. Here we look at the code as if we were creating a new component constructor. Subclass Sub inherits parent Vue, and refers the constructor back to itself. Then define its own component ID, merge OPTIONS, and define a property super pointing to Vue. The following comment explains that the props and computed are accessed by proxy, and then the methods mounted by Vue are also mounted to Sub…. Anyway a lot of mount for easy access. The sub. sealedOptions attribute is defined with a extend method, which is not related to vue. extend, but implements the object. assign function. Finally, cachedCtors[SuperId] = Sub is executed to store the constructor in the OPTIONS attribute _Ctor. This explains the previous constructor cache and prevents the constructor from being created twice.

As usual, when we use elementUI’s message prompt, we call it directly on the Vue instance via the this.$message method. It would be too cumbersome to show and hide component labels in the component template like popboxes. So, for example, we can implement a function using loading component

<! Define basic component parameters -->
<template>
    <div class="loading-wrap" v-show="visible">
        <div class="loading-box">
            <div class="loading"></div>
            <div class="text" v-show="!!!!! text">{{text}}</div>
        </div>
    </div>
</template>

<script>
    export default {
        name:'loading',
        data(){
            return {
                visible:false.text:' '}}}</script>

<style scoped>
    /* css */
</style>
Copy the code
// Encapsulate the plug-in method
import Vue from 'vue'
import loading from 'loading parameters' 
const Ctor = Vue.extend(loading)  // Generate the constructor
let instance = null
function Loading(Vue){
    // This is available in each Vue component instance
    Vue.prototype.$loading = {
        show:function(text){
            if(! instance){ instance =new Ctor() 
                instance = instance.$mount()
                instance.text = text
                instance.visible = true
                document.body.appendChild(instance.$el)
            }else{
                instance.text = text
                instance.visible = true}},hide:function(){
            if(! instance)return 
            instance.text = ' '
            instance.visible = false}}}export default Loading

Copy the code

Finally, register the plugin with vue. use in main.js.

Online Demo Address Complete project address

Vue.nextTick

Corresponding to the nextTick method, DOM updates triggered by Vnode changes are asynchronous, and Vnode changes until DOM updates are complete as an event loop. So if you want to access the updated DOM, you need to do so at the beginning of the next Tick.

function nextTick (cb, ctx) {
    var _resolve;
    callbacks.push(function () {
      if (cb) {
        try {
          cb.call(ctx);
        } catch (e) {
          handleError(e, ctx, 'nextTick'); }}else if(_resolve) { _resolve(ctx); }});if(! pending) { pending =true;
      timerFunc();
    }
    // $flow-disable-line
    if(! cb &&typeof Promise! = ='undefined') {
      return new Promise(function (resolve) { _resolve = resolve; }}})Copy the code

Callbacks store callbacks that need to be executed for the nextTick. Here you can see nextTick being used in two forms: a callback function as an argument to nextTick, and the resolve method in Promise. The pending variable controls the execution of timerFunc only once at a time, so you can see that all of these operations are synchronous. After nextTick is executed, the timerFunc method is executed. If you look at timerFunc, you’ve done some compatibility processing to make the flushCallbacks method execute asynchronously. To flushCallbacks is to take the methods that are stored in the callbacks and run them one by one.

Here’s another example

<template>
    <div class="common-wrap">
        <h2>NextTick demo</h2>
        <h3 id="msg1">{{msg1}}</h3>
        <h3 id="msg2">{{msg2}}</h3>
        <button @click="handleNextTick">My PM me</button>
    </div>
</template>

<script>
    export default {
        name:'nextTickDemo',
        data(){
            return {
                msg1:Content of the '1'.msg2:Content of the '2'}},methods:{
            handleNextTick(){
                this.msg1 = 'Content 1 Modification'
                this.$nextTick((a)= >{
                    console.log(document.querySelector('#msg2').textContent) / / # 1
                    console.log('View updated 1')})this.$nextTick((a)= >{
                    console.log('View updated 2')})this.msg2 = 'Content 2 Modification'}}}</script>
Copy the code

In the first nextTick callback after the button is clicked, the output value of the #1 line should be content 2 modified, corresponding to the value of the subsequent modification, which is also explained here. When handleNextTick is executed, assignment and nextTick are executed synchronously. When Msg1 is modified, it is executed as an asynchronous task, and the callback added by nextTick is executed in the second asynchronous task. The subsequent MSg2 assignment does not generate new asynchronous tasks because it is in the same Wathcer object as MSg1. So when the nextTick callback is executed, the DOM corresponding to MSG1 and MSG2 has been updated.

Vue.set

When initializing a Vue instance, the Object attribute descriptor is set via Object.defineProperty. Therefore, when a new attribute is added directly, Vue cannot detect it. Look at the set method, which ends with defineReactive? 1 proxy new properties, new properties do not need to do dependency collection here, directly update the new Vnode dependency collection.

Vue.delete

Delete a property. Deleting a property directly cannot be detected by Vue, and the documentation says that you should use it rarely. You can also set the property to null or undefined to trigger a response.

Vue.directive

Custom instructions can be used to reduce the need to write some repetitive code, which is not easy to explain. Just look at the documentation and how the V-Model is packaged in the source code.

Vue.filter

Filters, this is easier to use, because just look at the demo.

Vue source code uses the ASSET_TYPES array to save the three strings of Component, directive and filter. These three methods register special points.

Vue.component

The usual way to register components globally is to generate component constructors. The first argument to the method is the component name; The second argument is component options (the second argument, if empty, returns the constructor for the component name). The component’s constructor is returned using vue.extend when registered and stored in the Vue.options.components object, with key values accessed using the component name.

Vue.use

A method used to install a Vue plug-in that accepts a function or object. If it is an object, the install method is required. If it is a function, it is executed as the install method and Vue is passed in as the first argument.

function initUse (Vue) {
    Vue.use = function (plugin) {
      var installedPlugins = (this._installedPlugins || (this._installedPlugins = []));
      if (installedPlugins.indexOf(plugin) > - 1) {
        return this
      }

      // additional parameters
      var 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

Looking at the source code, you define an _installedPlugins array in the Vue so that each plug-in is registered only once. Unshift adds Vue to the first argument. After the plugin method is executed, save _installedPlugins and return Vue. Use is then chained to vue.use (plugin 1).use(plugin 2).

Vue.mixin

Global mix methods or properties, because the change is vue. options, this is merged into all Vue instances, so every component can access them. For vuE-Router and vuex, the beforeCreate periodic function is used for both applications. The $router and $store attributes are added for each component. For vue-Router and vuex, the beforeCreate periodic function is used for both applications.

Vue.compile

Official explanation: Compile a template string into the render function, available only in the full version. I: here is not analysis, not in-depth understanding.

Vue.observable

Make an object responsive, view the source code

Vue.observable = function (obj) {
    observe(obj);
    return obj
};
Copy the code

Observe the same use of Observe to make the object responsive as the initialization component. I’m going to use a little chestnut here as well.

<script> import Vue from 'vue' let normalData = { key: } export default {name:'observableDemo', render(h){return h('h3', {class:"common-wrap"}, 'become a responsible object, Attributes will be modified after one second: ${normalData.key}` ) }, Created (){Vue. Observable (normalData) window.setTimeout(()=>{normaldata.key = 'this is a response property'},1000)}} </script>Copy the code

Vue.version

Return the Vue version number

So that’s a brief look at the global apis in the Vue documentation.