VUE之组件的动态注册和动态加载

Posted 早饭君

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
    },

以上是关于VUE之组件的动态注册和动态加载的主要内容,如果未能解决你的问题,请参考以下文章

vue项目中动态加载路由组件this.$route undefined

vue -- 动态加载组件

Vuejs 中的动态导入

vue路由自动加载、按组件异步载入vuex以及dll优化

Vue 动态图片加载路径问题和解决方法

vue动态加载组件