新闻资讯

新闻资讯 行业动态

vue动态组件与异步组件之间的辛路历程

编辑:008     时间:2020-02-17

首先说下项目需求:单页应用中点击菜单项后动态响应页面中的tab标签(非浏览器的tab标签),tab标签对应一个页面,这将使得页面的显示由菜单主导,一般想法是点击菜单后动态显示组件,可组件怎么显示呢?

查阅vue官方文档,有个自带的动态组件

<component v-bind:is="需要动态显示的组件名"></component>

要使动态组件不随tab切换而变动(实际上每改变一次is都会new一个组件),还得加上keep-alive

<keep-alive>  <component v-bind:is="需要动态显示的组件名"></component> </keep-alive>

咋一看好像需求成了,可认真一看<component>中的is需要指向已打包的组件(一般就是明确用import导入的组件),那要是组件多起来,不仅要很多import,还得在vue当前组件的components中写入好些组件映射,麻烦!最主要的是项目大起来,这么写的后果会使得webpack打包的项目体积增大,对于一个单页应用,开发者和用户都不希望看到一个页面加载太长时间吧。

接着看官方文档,后面有个新概念——异步组件,看着是个好东西,官方推荐写法:

Vue.component( '组件名',  () => ({ // 需要加载的组件 (应该是一个 `Promise` 对象)  component: import('组件相对路径'),  // 异步组件加载时使用的组件  loading: loading,  // 加载失败时使用的组件  error: error,  // 展示加载时组件的延时时间。默认值是 200 (毫秒)  delay: 200,  // 如果提供了超时时间且组件加载也超时了,  // 则使用加载失败时使用的组件。默认值是:`Infinity`  timeout: 3000  })
);

马上着手并入自己的代码中,想当然的把import中的组件路径改为一个变量,加上去后编译就报错了,原来import不能这么玩,必须尽可能的明确路径。

粗略的认为,这个“异步组件”之路又不可行了,接着我考虑是否可以用ajax方式自行加载vue文件并解析呢?开始实干,接入http ajax库 axios (顺便照着网上的博文封装了一个http.js),正式加载组件,代码样本如下:

this.$http.axiosGet("./static/pages/Home2.vue")
  .then((result) => { var comContent = result.data; //加载获得的组件内容  Vue.component("组件名", {template: comContent});  //或者使用Vue.extend  })
  .catch(err => {
      console.log(err)
    }
  );

这下又踩坑了,一般的纯template组件,完全没问题,可vue组件文件中还有<script>代码啊,代码不执行咋办?难道我在加载完后在外部给它设置data等相关属性或函数,那加载的这块岂不是得写得非常非常非常臃肿?(这种方式我在bootstrap + jquery + vue模式中使用过,vue仅仅作为简单的数据绑定容器,全面使用vue后,肯定不能再这么干了)。

好吧,继续走在坑洼的道路上,难道就没有其它方式了?答案肯定是有的,记得我在对vue做技术评估时,初次尝试vue组件的便利,使用了一款开源组件加载器:httpVueLoader.js 按理说这也是一款神器,在不使用vuecli的情况下在简单的html文件中动态加载vue文件并能实现其中的<script>和<style>,非常了不起! 。。。。。。来转折了,但是呢,不兼容依据webpack写的组件,比如import语法,“export default” 还得改为 “module.exports=”,所有import导入组件全得改为在当前组件的依赖组件components中使用httpVueLoader加载,要是全部这么写,倒是没啥问题,要是正如vuex vueRouter呢,没这么整过,反正想着应该不够友好。如果仅仅是简单的使用vue给组件模板赋值显示,httpVueLoader.js也是一个很好的选择!

放弃 httpVueLoader.js 这条路后呢?有些人说:坚持就是胜利,就应该一条路走到黑,不过吧,毕竟写程序需要理智,不能脑袋抽风!虽然走了三条路,三条路都被我一一排查、验证和否定,但……,就没有我疏漏的地方?我再次反复观看官方文档,既然官方推荐这样做,肯定是有道理的,那么,又回到我走过的第一条路吧。

既然import不能使用变量是因为import中必须尽可能的明确组件路径地址这条硬性限制,我是否可以将import中的内容改为 "组件路径”+组件名的方式呢,经过验证,是可行的,最终用法如下:

Vue.component(
  comName,  () => ({ //import应该尽可能的缩小path范围,不然会出错  component: import('../../static/pages/' + comName),  loading: asynLoading,  error: asynError,  delay: 200,  timeout: 3000  })
);

解决!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐