VUE之組件的動態註冊和動態加載

目錄

問題描述

項目中的應用

使用總結


問題描述

實際項目中,針對不同的數據開發了不同的數據展示視圖組件,例如:拓撲圖、熱力圖、地圖。每一類視圖都有一個獨立的.vue組件,在界面化管理平臺上,要實現可以動態的新增視圖組件,同時修改的時候可以隨意的修改選擇那一類視圖。而且隨着項目的擴大,基礎視圖組件的也會隨之增加,即:基礎視圖組件的個數是不固定的。

這就要求在界面化操作配置視圖時,我們可以動態的註冊和加載組件。關於動態註冊及加載組件,網上有很多例子,看到轉載最多的就是這篇博文,講解了Vue的四種動態加載的方式,寫的很好,但是最初我一直無法很好的切入到實際項目中。另外一個比較常見的例子就是關於tab頁的切換,通過使用Vue的compent的:is屬性來動態切換使用那一個組件,關於這種方案,有很多博文,例如這篇博文,非常的直觀清晰。但是搜到的相關博文中,大多是需要事先把相關組件import進來,然後再動態的切換組件,並不能做到動態的註冊然後動態的切換。

這篇博文寫的非常好,他描述的問題和我遇到的問題基本一致,然後他提出了三種方案,我都分分別進行了嘗試,最後使用註冊局部組件的方式解決問題。下面來看下我實際遇到的問題。

項目中的應用

實際開發中,有一個panel.vue組件,用來維護面板信息,其中在修改面板時,可以選擇面板的視圖類型,這是一個下拉選擇的效果,在選擇了不同的數據視圖之後,渲染不同的組件。

<component :is="zjName" :resData="zjResData"></component>

其中:zjName是組件,zjResData是該組件對應的數據信息。如何動態的註冊並引入組件呢?

zjName:function(){
        var t_url = '';
        if(!ctool.strIsEmpty(this.panelObj.res_data)){
          t_url =  this.panelObj.pt_url;
        }else{
          t_url = this.pt_url;
        }
        if(this.panelObj.type!=0 && !ctool.strIsEmpty(t_url)){
          var myComponent =() => import(`./../../components/custom_panel/${t_url}.vue`);
          //var myComponent = resolve => require.ensure([], () => resolve(require(`./../../components/custom_panel/${t_url}.vue`)));
          //var myComponent =require(`./../../components/custom_panel/${t_url}.vue`).default;
          //var app_url = {t_url : require(`./../../components/custom_panel/${t_url}.vue`).default};
          return myComponent;
        }
        //Vue.component(t_url, res => require([`./../../components/custom_panel/${t_url}.vue`], res));

        return t_url;
      }

上述是計算屬性種的一個方法,主要是用來動態的返回組件的,可以看到有幾種註冊方式。

很顯然,直接通過import或者require得到的組件就可以直接給到is屬性即可。我之前一直在糾結組件名稱,所以不管怎樣做,都始終無法正確的渲染組件,其實,直接把組件給到is屬性即可,不需要組件名稱。

使用總結

(1) 在搜索相關博客的時候,不少人包括我自己都遇到了說沒有template或者render函數的錯誤提示,很多人都是在這是vue2.0升級後vue-loader大於13.0的版本的問題,使用require時候在後面加.default即可,經過驗證,確實是這樣,如果vue-loader版本爲12.0.3,直接使用require即可,按時如果版本是14.2.4就需要default.

(2) 組件中如果有setInterval定時執行的定時任務,那麼即便在組件銷燬後,該定製任務還是會繼續執行,所以需要在beforeDestory鉤子函數中,清楚定時器,參考這篇博文

(3) vue組件在mounted中使用setTimeout()失效,使用es6的箭頭函數可以解決,例如:

mounted() {
      //不加延時的話,取div寬度爲20,有問題
      setTimeout(()=>{
        this.initAll();
      },500);
    },

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章