Vue 动态组件按需加载
在软件解决方案中,存在三七定律,vue也不例外。通俗的讲,就是30%的基本API能解决70%的问题,剩下30%的问题就需要非常规性方法解决。今天我们要讲的也算是一种特殊场景,需要使用到一些非常规性手段。
业务场景
最常接触到的一种场景就是通过鼠标拖拽组件生成h5页面,类似积木。 活动模板根据接口数据决定展示哪几个组件
这类场景我的疑问是:
如果组件库有100个组件,我拖拽的生成的页面中只使用了其中5个组件,如何保证最终webpack打包生成的代码只含有这5个组件的代码,不包含其他冗余代码?
动态组件
文件目录结构
.
├── component
│ ├── LoadSyncComps.js
│ ├── TestA.vue
│ └── TestB.vue
└── index.vue
<!--TestA.vue-->
<template>
<div>{{name}}</div>
</template>
<script>
export default {
name: 'TestA',
data() {
return {
name: 'testA模块'
}
}
}
</script>
<!--TestB.vue-->
<template>
<div>{{name}}</div>
</template>
<script>
export default {
name: 'TestB',
data() {
return {
name: 'testB模块'
}
}
}
</script>
require + component 动态加载组件方案:
<!--index.vue-->
<template>
<div>
<component v-for="(item, index) in ary" :is="item.app" :key="index"></component>
</div>
</template>
<script>
export default {
data () {
return {
comps: ['TestA'],
ary: []
}
},
created () {
this.loadComp();
},
methods: {
loadComp() {
this.comps.forEach(app => {
this.ary.push({app: require(`./component/${app}.vue`).default})
})
}
}
}
</script>
这种方式是require + component
结合实现的,利用require
实现动态加载,component
做组件切换。
但是这种方案只实现了动态加载功能,并未实现按需加载。通过查看打包后的代码,会发现TestB.vue
未被引用,但是也被打包进去了。require
是CommonJS规范,在同路径下的vue文件,都会被打包进去。如果组件不是特别多的情况下,这种方法可以满足大部分场景。
动态组件 & 按需加载
可以使用ES6中的import
方法,该方法不同于import A from B
,这种属于纯静态编译,无法实现动态加载。为了实现动态加载,引入了import()
方法,该方法属于动态编译,webpack在打包时,碰到import()
方法,会单独生存一个独立文件,用于按需加载。
import + component 动态加载组件方案:
<!--index.vue-->
<template>
<div>
<component v-for="(item, index) in ary" :is="item.app" :key="index"></component>
</div>
</template>
<script>
export default {
data () {
return {
comps: ['TestA'],
ary: []
}
},
created () {
this.loadComp();
},
methods: {
loadComp() {
this.comps.forEach(app => {
this.ary.push({app: () => import(`./component/${app}.vue`)})
})
}
}
}
</script>
除了使用vue提供的component
,我们还可以使用Vue.extend
自己封装动态组件
require + Vue.extend
<!--LoadSyncComps.js-->
import Vue from 'vue';
const LoadSyncComps = Vue.extend({
props: {
comps: {
default: []
}
},
render(createElement) {
const list = [];
this.comps.forEach(item => {
const comp = require(`./${item}.vue`).default
<!--或者使用import-->
<!--const comp = () => import(`./${item}.vue`);-->
list.push(createElement(comp));
});
return createElement('div', list);
}
})
export default LoadSyncComps;
<!--index.vue-->
<template>
<div>
<LoadSyncComps :comps="comps"/>
</div>
</template>
<script>
import LoadSyncComps from './component/LoadSyncComps';
export default {
components: {
LoadSyncComps
},
data () {
return {
comps: ['TestA']
}
}
}
</script>
“在看转发”是最大的支持
评论