Vueソース分析(2)--一例から

4345 ワード

前言
本文はvue 2.xソース分析の第2編は、主にVueの初期化過程を説明します!
1、全文を貫く例:



  
  Vue
  


  
{{message}}
var app=new Vue({ el:'#app', name:'app', mixins:{ beforeCreate(){ console.log('beforeCreate-1'); } } props:['header-value'], data:{ message:'hello' }, beforeCreate(){ console.log('beforeCreate-2'); }, computed:{ abc(){ return this.message+'s' } }, components:{ ABF:'abf' }, directives:{ v-focus:function some(){} }, extends:{ ext_a:'a' }, methods:{ methods_a:function(){ alert('methods_a') } }, watch:{ 'message':function(){ console.log('message changed'); }, methods_a:function(){} } }) // debugger; // setTimeout(()=>app.message='world',0)

ここではまず簡単な例を置いて、分析が進むにつれて、一歩一歩例を複雑にします.分析の手段は,ブレークポイントを設定することによって実行過程を一歩一歩見ることである.
2、new Vue({})実行過程分析
  • まず、Vueコンストラクション関数(IDEの検索機能を有効にするとすばやくロックできる)
  • を見つけます.
    function Vue$3 (options) {
      if ("development" !== 'production' &&
        !(this instanceof Vue$3)) {
        warn('Vue is a constructor and should be called with the `new` keyword');
      }
      
      this._init(options); //     
    }
    
  • 上記のコードのdebuggerコメントを開いて分析します.init関数は、initMixin(Vue)によってVueに定義.prototypeの
  • Vue.prototype._init = function (options) {
        var vm = this;
        //   vm          _uid  
        vm._uid = uid++;
        // startTag, endTag         ,      ,  Unknown-2.1
        var startTag, endTag;
        /* istanbul ignore if */
        if ("development" !== 'production' && config.performance && mark) {
          startTag = "vue-perf-init:" + (vm._uid);
          endTag = "vue-perf-end:" + (vm._uid);
          mark(startTag);
        }
    
        //   _isVue       ,  Unknown-2.2
        vm._isVue = true;
        //     
        if (options && options._isComponent) {
          initInternalComponent(vm, options);
        } else {
          //      -1(    )
          vm.$options = mergeOptions(
            resolveConstructorOptions(vm.constructor),
            options || {},
            vm
          );
        }
        /*      */
        {
          initProxy(vm);
        }
        //  vm      _self   ,  Unknown-2.3
        vm._self = vm;
        //       -2(        )
        initLifecycle(vm);
        initEvents(vm);
        initRender(vm);
        callHook(vm, 'beforeCreate');
        initInjections(vm); // resolve injections before data/props
        initState(vm);
        initProvide(vm); // resolve provide after data/props
        callHook(vm, 'created');
    
        /* istanbul ignore if */
        if ("development" !== 'production' && config.performance && mark) {
          vm._name = formatComponentName(vm, false);
          mark(endTag);
          measure(((vm._name) + " init"), startTag, endTag);
        }
    
        if (vm.$options.el) {
          //       -3(    、       )
          vm.$mount(vm.$options.el);
        }
      };
    
  • で見ることができますInit関数は主に以下の3つのことをして、上述のコードは表示があります
  • 主にプロシージャ-1(マージオプションプロシージャ)
  • を実行
  • 主にプロシージャ-2(インスタンスの初期化プロシージャ)
  • を実行する.
  • は主にプロセス-3(依存収集、コンポーネントマウントなどのプロセス)
  • を実行する.
  • この3つのことは後で単独で分析されます.この3つのことのほかに、initProxy(vm)
  • を見てみましょう.
    initProxy = function initProxy (vm) {
        //     Proxy   
        if (hasProxy) {
          //            
          var options = vm.$options;
          var handlers = options.render && options.render._withStripped
            ? getHandler
            : hasHandler;
          vm._renderProxy = new Proxy(vm, handlers);
        } else {
          vm._renderProxy = vm;
        }
    };
    

    ここではProxy類に慣れていないかもしれませんが、まずここを見て基本的な使い方を知ることができます.実はvmインスタンスにhasHandlerエージェントを作成し、エージェントオブジェクトを_に掛けます.renderProxyでvm.renderProxyオブジェクトのプロパティはhasメソッドを呼び出し、値が真であることを返してプロパティを取得します.これは後ろにあります.render関数が使用されます
    3、まとめ
  • 次の分析内容☑ 主要実行プロセス-1(連結オプションプロセス)≒主要実行プロセス-2(インスタンスの初期化プロセス)≒主要実行プロセス-3(収集依存、コンポーネントマウントなどのプロセス)
  • 遺留問題解決状況▷Unknown 2.1 ☐ Unknown2.2 ☐ Unknown2.3