Vue应用中,组件肯定是不可避免地大量使用的,目前来说流行的做法是使用单文件组件,然后使用 Webpack + Vue-loader 进行打包。好,其实本文跟这个无关。本文说的是,有时候我们会有动态选择组件的需求。
应用场景描述
举一个实际应用的场景吧。
维基百科有大量这样的信息框,在信息框内各个项目都有不同的类型,可能是文本、数字、坐标或者其他。为了结构化数据,每种项目肯定要使用不同的表现方式,MediaWiki 下的解决方案是使用 模板(Template),而如果我们构建一个 Vue 应用,就应该是不同的组件负责不同的项目了。
为了下文描述方便,在此定义一个假想的数据结构。
[{
"id": 1,
"type": "location",
"data": {
"longitude": "xxxx",
"latitude": "yyyy"
}
}, {
"id": 2,
"type": "plaintext",
"data": {
"text": "zzzzzz"
}
}]
使用 component 标签的 is 属性
Vue 本来就为这种需求设计了解决方案。
首先我们做两个组件,并全部 import 。
<template v-for="item in infoBox">
<component
:is="item.type"
:data="item.data"
:key="item.id"
>
</component>
</template>
导入的时候则注意需要定义好子组件的名字。
import Location from '@/components/infoBox/location.vue';
import PlainText from '@/components/infoBox/plaintext.vue';
export default {
components: {
"location": Location,
"plaintext": PlainText
}
}
特别注意,如果像本例一样是遍历列表进行渲染的话,一定要加上key属性。(如果没有,在Vue 2.x 之后会有报错),因为在元素复用的时候可能会出现问题。(血泪教训,当初坑了好久)
参考官方文档
Functional Component
如果你的子组件没有自己的状态,非常简单,比如上面的 PlainText 组件,或许可以使用函数式组件来定义子组件。

