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 组件,或许可以使用函数式组件来定义子组件。