1. 程式人生 > >Vue.mixin Vue.extend(Vue.component)的原理與區別

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