Vue 中的动态组件实现

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

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注