Vue: 按需加载的动态组件与异步导入实践指南
动态组件&异步导入
动态组件搭配异步导入作为webpack编译组件的基础,提高代码可读性的同时使项目更加轻量且简洁。
本文介绍在Vue项目开发中,动态组件、异步导入过程及实践
动态组件
动态组件渲染使用 is
attribute属性 来切换不同的组件:
<component v-bind:is="currentTabComponent"></component>
每次切换新标签。Vue都创建了一个新的currentTabComponent
实例。
重新创建动态组件的行为尽管是非常有用的,但是某些标签组件实例内部数据不会发生变化,如果希望能够在第一次被创建的时候被缓存下来,可以用<keep-alive>
元素将其动态组件包裹起来。
<!-- 失活的组件将会被缓存!-->
<keep-alive>
<component v-bind:is="currentTabComponent" ></component>
</keep-alive>
异步组件
在大型应用开发中,组件的数量多且庞杂,此时组件的按需加载显得重要且必要。
Vue允许以一个工厂函数的方式定义组件,工厂函数会异步解析组件的定义。
Vue只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来渲染使用。
- require模式
webpack遗留功能require.ensure
Vue.component('async-webpack-example', function (resolve) {
// 这个特殊的 `require` 语法将会告诉 webpack
// 自动将你的构建代码切割成多个包,这些包
// 会通过 Ajax 请求加载
require(['./my-async-component'], resolve)
})
- import模式-推荐使用
在工厂函数中返回Promise
,利用es2015+webpack2动态导入:
Vue.component(
'async-webpack-example',
// 这个动态导入会返回一个 `Promise` 对象。
() => import('./my-async-component')
)
当使用局部注册时,直接返回Promise
函数:
new Vue({
// ...
components: {
'my-component': () => import('./my-async-component')
}
})
动态组件 && 异步组件导入
讲解实际项目案例、分析过程及要点
需求分析
项目工作流审批详情根据业务要求,需要展示每个模块独立的审批详情数据。
需求拆解
- 项目工作流审批详情页面属于公共页面,各自模块审批详情页面属于业务范畴。
- 在公共页面展示的不同模块的页面数据。
实现思路分析
- 公共页面提供页面整体布局,页面内容由各模块组件填充。
- 公共页面组件为动态的异步导入组件。
- 动态组件传递给各模块组件聚合参数及方法
- 组件数据整合为
JSON
的数组
代码实践
代码实践分三个部分组件数据、页面渲染、异步导入
JSON
的组件数据
在大型应用中,可以用在线excel收集组件信息,组件路径可以直接粘贴组件的相对路径,再用脚本处理成标准的可直接使用的JSON
数组做半自动化处理。
[
{
"id": 111,//组件编号
"urlPath": "src/components/Card.vue",//组件相对路径
"tag": "Card",//组件名称
"extra":{}//冗余参数
},
{
"id": 112,
"urlPath": "src/components/Message.vue",
"tag": "Message",
"extra":{}
}
]
公共详情页面配置
公共详情页面此刻作为一个壳子,各自的模块组件放在壳中,代码示例:
<template>
<div class="hello">
<!--带缓存的动态组件-->
<keep-alive>
<component v-bind:is="currentTabComponent" :extra="extra" @updateCom="updateComponent" class="tab"></component>
</keep-alive>
</div>
</template>
<script>
import componentList from "../work/components.json"//导入组件数据
import components from "../work/dataFlow";//组件异步导入
export default {
name: "HelloWorld",
components,//立即执行的异步导入组件
data() {
return {
msg: "Welcome to Your Vue.js App",
currentTabComponent: "Message",//当前渲染组件
extra:{}
};
},
created() {
//模拟异步请求返回数据
setTimeout({code,data} => {
//to do
let result= componentList.find(item=>item.id == +data.id)
let extra = result.extra
this.extra = Object.keys(extra).length>0?extra:data
this.currentTabComponent = result.tag;
}, 500);
},
methods:{
updateComponent(){
//to do
}
}
};
</script>
渲染过程
异步导入的组件整体在dataFlow.js中处理,示例代码:
// dataFlow.js
import list from '../work/components.json'
var result = ( ()=> {
let component = {};
for (let i = 0; i < list.length; i++) {
let com, path;
com = list[i]
path = com['urlPath'].substring(4,com['urlPath'].length)
component[com.tag] = ()=>import(`@/${path}`)//注意要点
}
return component
})()//立即执行函数
export default result
要点剖析
1、import无法导入变量字符串作为路径
导入失败写法:
let path = '@/components/Message.vue';
let com = ()=>import(path)
导入成功写法:
let path = '@/components/Message.vue';
copyPath = path.substring(2,path.length)
let com = ()=>import(`@/copyPath`)
webpack目前不支持完全意义上的动态导入。
可以通过字符串模板功能帮助webpack识别主要路径,这样编译时会编译src下的模块,但组件的只有在被渲染时才加载,从而实现异步导入。
2、立即执行函数
异步组件的导入处理成立即执行函数,会在页面调用时导入的components
函数作为变量直接被执行导入过程,避免导入的函数再次调用。
参考资料
Vue-动态组件&异步组件
webpack-动态导入
es6-import()