优化案例:商品卡不同类型代码如何实现
刀刀
7/16/2025
0 字
0 分钟
- 来源:三十的前端课;视频地址:前端中的设计模式应用
案例详情
有一个随着类型变化,不断变化的商品卡片,有四种类型,其 UI 结构部分有差距,且后期还有可能增加其他类型,该怎么设计?
下面来看看简单版的 UI:
难点分析
- 商品类型多,有相似有不同,怎么设计提高复用性
- 后续还会增加类型,如何确保可拓展性
组合模式
组合模式核心是把商品按树状结构拆分,然后按需把各个部分组装起来。例如可以划分为以下几点:
- 商品容器:规定商品
padding
、margin
等样式,并包含商品信息容器和商品媒体容器 - 商品信息容器:包含商品标题、价格、描述等,其中可以更细致的拆分一下
- 秒杀条
- 热门信息
- 标题
- 价格
- 商品媒体容器:包含视频组件和图片组件
- 视频组件
- 图片组件
商品容器就是这个树状结构的根,商品信息容器和商品媒体容器是根的子节点,视频组件和图片组件是商品媒体容器的子节点。这样设计的好处是,当商品类型增加时,只需要增加对应的子节点即可,不需要改动根节点,提高了可拓展性。
基础壳子:
vue
<script setup>
// 假设已经引入全部 compoment 内的子组件
</script>
<template>
<!-- 视频商品卡 -->
<div v-if="cardType === 'videoCard'">
<!-- 商品基础容器 -->
<GoodsContainer>
<!-- 媒体容器 -->
<MediaContainer>
<CardVideo></CardVideo>
<!-- 商品视频 -->
</MediaContainer>
<!-- 信息容器 -->
<InfoContainer>
<CardTitle></CardTitle>
<!-- 商品标题 -->
<CardPrice></CardPrice>
<!-- 商品价格 -->
<CardShopInfo></CardShopInfo>
<!-- 商家信息 -->
</InfoContainer>
</GoodsContainer>
</div>
<!-- 秒杀商品视频卡 -->
<div v-if="cardType === 'scekillvideoCard'">
<!-- 媒体容器 -->
<GoodsContainer>
<MediaContainer>
<CardVideo></CardVideo>
<!-- 默认插槽:放商品视频 / 图片 -->
<template #leftCard>
<CardScekill title="秒杀中"></CardScekill>
<!-- 左侧插槽:放秒杀信息 -->
</template>
</MediaContainer>
<!-- 信息容器 -->
<InfoContainer>
<CardTitle></CardTitle>
<!-- 商品标题 -->
<ScekillBar></ScekillBar>
<!-- 秒杀条 -->
<CardPrice></CardPrice>
<!-- 商品价格 -->
<ScekillPrice></ScekillPrice>
<!-- 秒杀价格 -->
</InfoContainer>
</GoodsContainer>
</div>
<!-- 热门商品视频卡 -->
<div v-if="cardType === 'hotvideoCard'">
<!-- 媒体容器 -->
<GoodsContainer>
<MediaContainer>
<CardVideo></CardVideo>
<!-- 默认插槽:放商品视频 / 图片 -->
<template #leftCard>
<CardScekill title="秒杀中"></CardScekill>
<!-- 左侧插槽:放秒杀信息 -->
<CardScekill title="热卖中"></CardScekill>
<!-- 左侧插槽:放秒杀信息 -->
</template>
</MediaContainer>
<!-- 信息容器 -->
<InfoContainer>
<CardTitle></CardTitle>
<!-- 商品标题 -->
<ScekillBar></ScekillBar>
<!-- 秒杀条 -->
<HotInfo></HotInfo>
<!-- 热卖信息 -->
<CardPrice></CardPrice>
<!-- 商品价格 -->
<ScekillPrice></ScekillPrice>
<!-- 秒杀价格 -->
</InfoContainer>
</GoodsContainer>
</div>
<!-- 图片商品卡 -->
<div v-if="cardType === 'imageCard'"></div>
</template>
策略模式与状态模式
上方的模式是在一个父组件中 v-if
判断要渲染哪个卡片,然后组合对应的子组件。这种模式在卡片数量较少时,代码可读性高,但缺点是当卡片数量增加时,代码会变得冗长,难以维护。
可以使用策略模式,将每种卡片类型抽离成一个独立的组件,父组件引入全部的组件,通过动态组件动态切换卡片的形式。
vue
<template>
<component :is="cardType"></component>
</template>
<script setup>
import VideoCard from "./VideoCard.vue";
import ScekillVideoCard from "./ScekillVideoCard.vue";
import HotVideoCard from "./HotVideoCard.vue";
import ImageCard from "./ImageCard.vue";
const cardType = "xxx";
const cardList = {
videoCard: VideoCard,
scekillVideoCard: ScekillVideoCard,
hotVideoCard: HotVideoCard,
imageCard: ImageCard,
};
</script>