Vue 動態組件渲染問題分析

firevue

讀在最前面:node

  一、本文適用於有必定基礎的vue開發者,須要瞭解基本的vue渲染流程app

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


問題描述:spa

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

 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')
        ]);
      },
    });

  

點擊查看實例代碼3d

 

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

 

關鍵執行順序分析:對象

一、App經過繼承Vue生成構造,Child經過繼承App生成構造blog

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

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

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

  3.二、在_createElement的時候 node 當爲component options / constructor 時,會驗證是否 node 是否爲object,若是是會轉換爲構造器 使用vue.extend

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

 

 

最後附上大體流程圖:

 

 

 

備註:  

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

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

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

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

 by:海豚灣-豐

相關文章
相關標籤/搜索