vue动态组件与异步组件之间的辛路历程
首先说下项目需求:单页应用中点击菜单项后动态响应页面中的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 }) );
解决!
再次,感谢 https://m.jb51.net/article/143925.html 这篇博文作者对webpack import做了细致分析!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
Spring 源码(九)@Autowired注解实现原理(Spring Bean的自动装配)
@Autowired注解的实现过程,其实就是Spring Bean的自动装配过程。通过看@Autowired源码注释部分我们可以看到@Autowired的实现是通过AutowiredAnnotationBeanPostProcessor后置处理器中实现的。 AutowiredAnnotationBeanPostProcessor 类图 PriorityOrdered:确认 AutowiredAnnotationBeanPostProcessor 后置处理器的执行优先级 BeanFactoryAware:使得AutowiredAnnotationBeanPostProcessor 可以直接通过BeanFactory获取容器中的Bean BeanPostProcessor:在 Bean 初始化前后执行的后置处理器 InstantiationAwareBeanPostProcessor:在 Bean 实例化前后和Bean设置属性值时执行的后置处理器 SmartInstantiationAwareBeanPostProcessor:智能实例化Bean的后处理器,如预测Bean的类型和确认Bea...
-
下一篇
死磕 java线程系列之创建线程的8种方式
(手机横屏看源码更方便) 问题 (1)创建线程有哪几种方式? (2)它们分别有什么运用场景? 简介 创建线程,是多线程编程中最基本的操作,彤哥总结了一下,大概有8种创建线程的方式,你知道吗? 继承Thread类并重写run()方法 public class CreatingThread01 extends Thread { @Override public void run() { System.out.println(getName() + " is running"); } public static void main(String[] args) { new CreatingThread01().start(); new CreatingThread01().start(); new CreatingThread01().start(); new CreatingThread01().start(); } } 继承Thread类并重写run()方法,这种方式的弊端是一个类只能继承一个父类,如果这个类本身已经继承了其它类,就不能使用这种方式了。 实现Runnable接口 publ...
相关文章
文章评论
共有0条评论来说两句吧...