需求
当我们的页面需要不定量的组件进行渲染时,我们可能会大量引入全部组件再使用动态组件完成需求,通过组件的动态引入减少代码量以及项目难度,我们需要掌握以下内容
动态组件
通过<component> 标签上的is 属性实现对组件的动态引用
<template>
<component :is="myComponent"></component>
</template>
is 属性的属性值可以为:
- 一个已注册过的组件的组件名
- 一个组件的选项对象
<template>
<component :is="myComponent"></component>
</template>
export default {
data(){
return {
myComponent:{
render(h){
return h('h1','这是我的组件')
}
}
}
}
}
异步组件
Vue 允许以一个函数的方式定义组件,这个函数会在组件需要被渲染的时候触发,并将结果缓存起来以便以后重新渲染
Vue.component('MyComponent',function(resolve){
resolve({
render(h){
return h('h1','这是我的异步组件')
}
})
})
或者返回一个Promise
export default {
components:{
MyComponent:function(){
return new Promise(resolve=>{
resolve({
render:h=>h('h1','这是我的异步组件')
})
})
}
}
}
import函数
再ECMAScript2020 中引入import 函数支持动态加载模块,参数与import 命令接受的参数相同,它返回一个Promise 对象
export default {
methods:{
handleImport(){
import('./a.vue').then(data=>{
console.log(data)
})
}
}
}
所以我们常用的异步组件写法
export default {
components:{
MyComponent:()=>import('./my-component.vue')
}
}
import 函数允许动态路径,但注意不能是纯动态的
例如import(foo),这样完全动态的加载方式将会失败,因为webpack需要一些文件位置信息。因为变量foo可能是系统或项目中任何文件的路径。import()必须至少包含关于模块所在位置的一些信息,因此让捆绑可以局限于特定的目录或文件夹。
内容参考自vue动态组件找不到module问题,import不能接收动态参数
所以我们可以使用以下方式进行动态引入
let fileName="user"
import('@/components/'+fileName+'.vue')
动态组件和异步组件结合实现功能
<template>
<component v-if="dynamicComponent" :is="dynamicComponent"></component>
</template>
export default {
computed:{
dynamicComponent(){
let filename=this.$route.params.filename
if(filename){
return ()=>import('@/components/dynamic-components/'+filename+'.vue')
}else{
return null
}
}
}
}
拓展1-处理加载状态
异步组件函数也可以返回一个对象
export default {
components:{
MyComponent:()=>({
component: import('./MyComponent.vue'),
loading: LoadingComponent,
error: ErrorComponent,
delay: 200,
timeout: 3000
})
}
}
拓展2-require方法
webpack支持require方法
AMD-require方法
require((paths:Array\<String\>[,callback:Function]))
方法链接
-
paths:引入的文件列表
-
callback:回调函数
我们也可以结合resolve 回调实现异步组件
Vue.component('MyComponent',resolve=>{
require(['@/components/my-component.vue'],resolve)
})
webpack-require.context方法
require.context(directory:String[,includeSubdirs:Boolean][,filter:RegExp][,mode:String])
方法链接
-
directory:组件目录的相对路径
-
includeSubdirs:是否查询子目录
-
filter:组件名匹配的正则表达式
-
mode:可用模式,默认值’sync’
通过require.context 方法检查组件是否存在
var context=require.context('@/components',false,/\.vue$/)
var keys=context.keys()
var moduleName=keys.find(key=>key.replace(/(^\.\/)|(\.vue$)/g,'')==this.$route.params.module)
var myComponent=moduleName?context(moduleName).default:null
|