动态加载是web应用的优化首屏加载的手段之一,webpack是支持import用于动态加载模块的。import作为函数调用时参数为文件路径,返回一个primise实例。
window.addEventListener('click', ()=>{
import(/* webpackChunkName: "test-module"*/"./test.js")
.then(module =>{
...
})
});
动态加载组件的实现手段是一样的,在合适的生命周期去调用import函数,并在返回后将组件挂到全局或父组件里(一般喜欢放入父组件里),修改父组件的数据导致视图更新,让未被渲染出来的动态组件显示。
import("./test.vue")
.then(component => {
//挂到全局
Vue.component('asyncComponent', component.default);
//挂到父组件
this.$options.components.asyncComponent = Vue.extend(component.default);
}
我一般喜欢抽离成一个组件去修饰一下,使之可公用并更优雅。
// asyncLoad.vue
<template>
<div>
<asyncComponent v-if="ready" v-bind="$attrs" v-on="$listeners"></asyncComponent>
<div v-else>
<span v-if="fail">组件加载失败,请刷新页面。</span>
<span v-else>加载中...</span>
</div>
</div>
</template>
<script>
import Vue from 'vue';
export default {
props: {
importFunction: {
require: true,
type: Function
}
},
data() {
return {
ready: false,
fail: false,
}
},
mounted() {
this.importFunction()
.then(com => {
this.$options.components.asyncComponent = Vue.extend(com.default);
this.ready = true;
})
.catch(err => {
this.fail = true;
})
},
}
</script>
// 动态加载使用者
<template>
<div>
<asynLoad :importFunction="loadComponent" />
</div>
</template>
<script>
import asynLoad from '../asyncLoad.vue';
const loadComponent = () => import("./test.vue");
export default {
data() {
return {
loadComponent,
}
},
components: {
asynLoad
},
}
</script>