Vue 動態組件渲染問題分析


fire

讀在最前面:

  1、本文適用於有一定基礎的vue開發者,需要了解基本的vue渲染流程

  2、本文知識點涉及vue構造器以及選項策略合並、<component> 渲染邏輯


問題描述:

Child繼承自App,主程序通過true 和false來控制顯示 Child 還是 App,在動態<component /> 中渲染出來的始終是App,代碼如下

 Vue.config.productionTip = false;
    Vue.config.devtools = false;

    // ----------------options---------------------
    const optionsA = {
      render: (h) => h('span', '我是options - 父'),
    };

    const optionsB = {
      render: (h) => h('span', '我是options - 子'),
    };

    const App = Vue.extend({
      template: `<div>
                    當前組件: {{name}}
                    <br/>
                    <component :is="node" />
                  </div>`,
      data() {
        return {
          name: 'App',
          node: optionsA,
        }
      }
    });

    const Child = App.extend({
      name: 'Child',
      data() {
        return {
          name: 'Child',
          node: optionsB,
        }
      }
    });

    const vm = new Vue({
      el: '#app',
      data() {
        return {
          isSuper: true,
        };
      },
      components: { App, Child },
      render(h) {
        const that = this;
        return h('div', {}, [
          h('button', {
            on: {
              click: () => {
                this.isSuper = true;
              }
            },
          }, '父類'),
          h('button', {
            on: {
              click: () => {
                this.isSuper = false;
              }
            },
          }, '子類'),
          h(this.isSuper ? 'App' : 'Child')
        ]);
      },
    });

  

點擊查看實例代碼

 

如下圖(點擊父/子類切換,始終顯示的是 父文本):

 

關鍵執行順序分析:

1、App通過繼承Vue生成構造,Child通過繼承App生成構造

2、默認isSuper:true,渲染出App(<component :is="node" /> 編譯為render: _C(node),這個時候會在App的node中生成.Ctor)

3、切換isSuper:false,渲染出Child(這里渲染的時候,生成的實例是App,這里是不符合預期的,按理應該是Child

  3.1、生成Child實例的時候進行了data合並,這個時候data中node變量合並了App的node中的.Ctor($options合並策略),參照下圖

  3.2、在_createElement的時候 node 當為component options / constructor 時,會驗證是否 node 是否為object,如果是會轉換為構造器 使用vue.extend

  3.2、在Child中動態調用 new Ctor() (這個Ctor是App的),生成實例

 

 

最后附上大致流程圖:

 

 

 

備注:  

   1、Vue.extend會生成VueComponent構造器,內部包含一個Ctor,組件生成的時候就是調用這個new Ctor() 進行實例生成

   2、選項中data的生成是延遲到實例生成的時候

   3、createComponent在分支<component>渲染時,傳入Ctor為對象的時候,會轉換為構造器,這也是我們這個使用 const optionsA = {render: (h) => h('span', '我是options - 父'), }; 這種方式的問題根源所在

   4、知道了問題所在,解決方式就比較多了,比如直接傳入構造器,比如繞開data值合並策略,使用method方式。

 by:海豚灣-豐

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM