一、需求场景
我们日常工作中遇到一种列表需要同时展示多种不同 cell 视图的场景(常见聊天列表和消息列表)。大部分人第一直觉就是 if 指令,这种方式虽然能实现,但是当样式超过两种,代码就会异常丑陋和不利于维护。实现这种需求最优雅的实现方式是动态组件实现:通过信息类型返回对应的组件,有些像 templet 中的工厂模式;
二、效果图(假设三种消息类型)
三、核心代码
//src/views/DynamicCompAdvanced.vue
<template>
<div class="page_container">
<navbar
isleftarrow
navBarTitle="动态组件进阶"
closeWebview
>
</navbar>
<component
v-for="(item, index) in items"
:key="index"
:is="currentComp(item.type)"//返回组件
:obj="item"//正常组件传值,此处传值为对象(typeMap中有所有组件必须有 obj 属性)
>
</component>
</div>
</template>
<script setup>
import navbar from '@/components/navbar.vue';
import DynamicCellOne from '@/components/DynamicCellOne.vue'
import DynamicCellTwo from '@/components/DynamicCellTwo.vue'
import DynamicCellThree from '@/components/DynamicCellThree.vue'
import {ref, reactive, computed} from "vue";
const items = reactive([
{
title: '热门活动',
content: '您收到一条热门活动',
icon: require('@/assets/images/icon_notice_popular.png'),
imgUrl: 'https://ys-oss-zjrs.haier.net/content/img/2022081016074732563876.jpg',
type: 5,
eventID: 'BD10030',
index: 0,
time: "2022-08-10 09:15",
},
{
title: '系统通知',
content: '您收到一条系统通知',
icon: require('@/assets/images/icon_notice_system.png'),
type: 0,
imgUrl: 'https://ys-oss-zjrs.haier.net/content/img/2022081016074732563876.jpg',
eventID:'BD10031',
index: 1,
time: "2022-08-11 11:15",
},
{
title: '进度消息',
content: '您收到一条进度消息',
icon: require('@/assets/images/icon_notice_schedule.png'),
imgUrl: 'https://ys-oss-zjrs.haier.net/content/img/2022081016074732563876.jpg',
type: 6,
eventID: 'BD10032',
index: 2,
time: "2022-08-12 19:15",
},
]);
// 所有类型和组件映射关系
const typeMap = {
5: DynamicCellOne,
0: DynamicCellTwo,
6: DynamicCellThree,
};
// 当前组件
const currentComp = (type) => {
const key = type.toString();
if (Object.keys(typeMap).includes(key)) {
return typeMap[key];
}
return typeMap[0];
};
</script>
<style scoped lang="scss">
.page_container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background-color: #f6f6f6;
}
</style>
总结
若是一个列表中需要展示多种(大于一种),都应该用动态组件实现,这样无论从代码量、维护性和扩展性上,都是最好的选择。