一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
一、什么是动态组件
学习动态组件之前,我们需要知道什么是组件。
对于组件官方是这样定义的:
组件是可复用的 Vue 实例
。就是说,组件也是Vue
实例,但是组件和vue
实例也有差异:
1. 组件没有挂载目标 el ,因为组件是跟着vue实例的,所有vue实例的挂载点也是组件的挂载点2. 组件中data不能是对象,因为vue实例是单例模式,只有一个,组件有多个。我们知道多个属性调用对象会指向统一地址,但是方法每new一个实例就会开辟一块新的内存空间。所以组件中不能是对象,必须是方法。
而动态组件就是动态变化的组件,和动态样式一样,通过用户的操作来确定是什么类型的组件。
动态样式是绑定
:style
,动态组件则是绑定:is
二、动态组件的具体实现
使用场景:需要的组件不确定时,可以使用动态组件的方式生成。例如:接收到一个文本数据,我们就动态生成一个文本组件。接收到一个图片数据,我们就动态生成一个图片组件。
实现思路:
首先需要定义json数据,每一项键值对存储类型数据
这里的
json
数据主要是用来存储组件类型,可以存储多个组件类型,为了方便我们就让它的type
对应组件的名称。这里的
json
数据采用默认导出的方法export default
,一个文件只有一个方法时就用默认导出。
export default = [{ id:1, type:'textComp'},{ id:2, type:'imageComp'}]
导入json数据,将数据存入data中
导入默认导出的js文件,不需要{}来接收。
因为我导入文件时经常忘记要不要{},所以这里复习一下导入的知识点:默认导入不需要{},命名导入需要{}
创建需要渲染的组件模板(
TextComp
、ImageComp
) 封装组件的时候尽量设置规范的name值(我之前喜欢小驼峰命名,但是不符合官方规范)。
我们在设置组件名时一定要遵守Vue给出的官方命名规范:要么始终字母开头大写,要么始终单词之间横线连接。例子:
反例:
mycomponent.vue
、myComponent.vue
。好例子:MyComponent.vue
、my-component.vue
引入所有组件模板
这里也是使用默认导入组件,因为组件内中
script
使用的导出方法为默认导出利用动态组件的标签,动态绑定
is
,渲染指定组件(本来可以变成,依靠is
来动态绑定样式)补充知识:
关于内置组件
component
的使用。这里参考一下Vue
官方的说明:#compoent
Props:
is
: string | ComponentDefinition | ComponentConstructor
inline-template
:boolean用法:
渲染一个“元组件”为动态组件。依
is
的值,来决定哪个组件被渲染
//动态组件由 vm 实例的 `componentId` proterty实例 <component :is='componentId'></component> //也能够渲染注册过的组件或 prop 传入的组件 <component :is='$options.components.child'><component>
总结:
component
可以通过is
动态渲染不同的组件
<template> <div id='app'> <component :is='textCompName'></component> </div> </template> <script>import textComp from './components/TextComp' data(){ return{ textCompName:'TextComp' } } </script>
通过
json
数据,动态渲染指定组件这里通过导入的
json
数据,通过v-for
遍历json
中每一项的type
,通过type
动态设置component
中的:is,从而生成动态组件如果
json
数据中的type
与组件名不同时,就要通过计算属性,遍历获取到dataList
的每一项并读取type
值。动态组件标签的is
绑定计算属性,由于是数组对象,可以使用v-for
<template> <div id='app'> <div v-for='item in getCompType' :key='item.id'> <component :is='item.type'></component> </div> </div> </template> <script> computed:{ getCompType(){ return this.dataList.forEach(item=>{ return { ...item, type:item.type+'Comp' } }) } } </script> <template> <div id="app"> <div v-for="item in dataList" //这里组件名和json中的type相同,也可以直接使用 :key="item.id"> <component :is="item.type"> </component> </div> </div> </template>
简单说一下
Array.prototype.map()
和Array.prototype.forEach()
的区别
forEach()
不返回执行结果,返回undefined
。forEach()
被调用,不改变原数组
map()
会产生新数组,并分配内存空间存储,并且不会修改原数组
完整代码:
TextComp.vue`
<template>
<div>文本组件模板</div>
</template>
<script>
export default {}
</script>
ImageComp.vue
<template>
<div>图片组件模板</div>
</template>
<script>
export default {}
</script>
<style></style>
dataList.js
module.exports = [{
id: 1,
type: 'TextComp'
},
{
id: 2,
type: 'ImageComp'
}]
App.vue
<template>
<div id="app">
<div v-for="item in dataList"
:key="item.id">
<component :is="item.type"></component>
</div>
</div>
</template>
<script>
import dataList from './data/dataList.js'
import imageComp from './components/ImageComp'
import textComp from './components/TextComp'
export default {
name: 'App',
data () {
return {
// 根据传入的json来实现组件动态绑定,前提是json中存在type且和组件名相同
dataList,
// 动态绑定 imageComp 组件,但是这里是写死的,我们需要根据传入的json数据来动态绑定组件
// componentId: ImageComp
}
},
components: {
ImageComp,
TextComp
}
}
</script>
效果展示:
补充知识:组件化与模块化的区别
相同点:都是为实现代码的高内聚、低耦合、提高复用率
不同点:
组件是一段代码集,包括
html
、css
、js
、image
;模块指的是js
代码。组件是封装一个功能;模块封装的是一个方法
模块和模块化、组件和组件化的区别:使用了组件化的形式编程就叫组件化
总结:
通过学习
Vue
动态组件,加深了我对vue
组件化的理解。也更清楚了组件化与模块化的区别组件化是
Vue
的精髓,Vue
应用就是通过一个个组件构成的。组件化有点类似与
js
中的模块化,同样是提高了代码复用。