Vue.mixin Vue.extend(Vue.component)的原理与区别

Posted riona

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue.mixin Vue.extend(Vue.component)的原理与区别相关的知识,希望对你有一定的参考价值。

1.本文将讲述 方法 Vue.extend Vue.mixin 与 new Vue({mixins:[], extend:{}})的区别与原理

     先回顾一下 Vue.mixin 官网如下描述:

     Vue.mixin( mixin )全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。

     既然可以影响到注册后的所有实例,那么该方法注入的方法和属性都存放在哪里呢(构造函数的options属性上),我们一起来看看该方法的定义

     Vue.mixin = function (mixin) {
             //mergeOption,将Vue构造函数的Options属性与传入的mixin参数进行合并,
             //合并之后再复制给Vue构造函数的Options属性
            this.options = mergeOptions(this.options, mixin);
            return this
        };

    为什么Vue.mixin方法将mixin合并至Vue.options就能影响注册之后的所有实例呢,让我们看看Vue实例化的过程(将构造函数的options属性与实例化参数合并后付给实例的$options属性

 

 1    function Vue(options) {
 2         //调用_init方法
 3         this._init(options);
 4     }
 5 
 6 
 7 
 8     Vue.prototype._init = function (options) {
 9             var vm = this;
10             // a uid
11             vm._uid = uid$3++;
12 
13             var startTag, endTag;
14     
21             // a flag to avoid this being observed 标记该对象是一个Vue实例
22             vm._isVue = true;
23             // merge options
24             if (options && options._isComponent) { //组件实例化过程,即Vue.extend返回对象--稍后解释
25                 // optimize internal component instantiation
26                 // since dynamic options merging is pretty slow, and none of the
27                 // internal component options needs special treatment.
28                 initInternalComponent(vm, options);
29             } else {//将构造函数的options属性与实例化参数合并后付给实例的$options属性 ,该属性会在函数initState中进行初始化
30                 vm.$options = mergeOptions(  
31                     resolveConstructorOptions(vm.constructor),
32                     options || {},
33                     vm
34                 );
35             }
36             /* istanbul ignore else */
37             {
38                 initProxy(vm);
39             }
40             // expose real self
41             vm._self = vm;
42             initLifecycle(vm);
43             initEvents(vm);
44             initRender(vm);
45             callHook(vm, beforeCreate);
46             initInjections(vm); // resolve injections before data/props
47             initState(vm);
48             initProvide(vm); // resolve provide after data/props
49             callHook(vm, created);
50 
51             /* istanbul ignore if */
52             if ("development" !== production && config.performance && mark) {
53                 vm._name = formatComponentName(vm, false);
54                 mark(endTag);
55                 measure(("vue " + (vm._name) + " init"), startTag, endTag);
56             }
57 
58             if (vm.$options.el) {
59                 vm.$mount(vm.$options.el);
60             }
61         };

 

     Vue.extend-- 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象 

     该方法返回一个与Vue具有相同功能的构造函数(其实为创建了一个组件)-属性options是 合并  基础 Vue 构造器 与 extend的参数 的对象,

     

 Vue.extend = function (extendOptions) {
            extendOptions = extendOptions || {};
            //将调用函数付给Super 
            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 ("development" !== production && name) {
                validateComponentName(name);
            }
            //创建组件Sub
            var Sub = function VueComponent(options) {
                this._init(options);
            };
       //为组件添加对应的属性与方法 Sub.prototype
= Object.create(Super.prototype); Sub.prototype.constructor = Sub; Sub.cid = cid++;
//合并super的options与extend的入参并赋值给Sub的options属性 Sub.options
= mergeOptions( Super.options, extendOptions );
//在sub上保存Super的信息 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
//如果有组件名称,将该组件挂载到sub.options.components上。以便可在组件内使用
          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.
//保存option信息。以便在render的时候生成最新的options选项
Sub.superOptions = Super.options; Sub.extendOptions = extendOptions; Sub.sealedOptions = extend({}, Sub.options); // cache constructor cachedCtors[SuperId] = Sub; return Sub //返回sub构造函数 };

Vue.component

 







以上是关于Vue.mixin Vue.extend(Vue.component)的原理与区别的主要内容,如果未能解决你的问题,请参考以下文章

vue mixin混入,生命周期执行阶段简易实现

vue mixin混入,生命周期执行阶段简易实现

vue mixin混入,生命周期执行阶段简易实现

如何使用 Vue 实例中的 Global Mixin 方法

为啥挂载在 Vue 插件或 Mixin 中会工作多次? [关闭]

深入浅析Vue中mixin和extend的区别和使用场景