【组件分享】商品列表组件-最佳实践

devtools/2025/1/23 11:42:58/

商品列表组件

商品列表组件用于展示商品信息列表,支持多种布局方式和自定义配置。
在这里插入图片描述

基础用法

<template><ProGoodsList :goods-list="goodsList" :layout="layout" @item-click="handleItemClick" />
</template><script setup>
import { ref } from 'vue';const layout = ref('grid'); // 'grid' | 'list'
const goodsList = ref([{id: 1,name: '商品名称',price: 99.99,image: 'https://example.com/image.jpg',description: '商品描述',},
]);const handleItemClick = (item) => {console.log('点击商品:', item);
};
</script>

API

Props

参数说明类型默认值
goodsList商品列表数据Array[]
layout布局方式String‘grid’
showPrice是否显示价格Booleantrue
showDescription是否显示描述Booleantrue

Events

事件名称说明回调参数
item-click点击商品项时触发(item: Object)
load-more加载更多时触发-

Slots

名称说明
item自定义商品项内容
empty自定义空状态内容

主题定制

组件支持通过 CSS 变量进行主题定制:

.pro-goods-list {--goods-item-bg: #ffffff;--goods-item-padding: 16px;--goods-item-radius: 8px;--goods-item-gap: 16px;--goods-price-color: #ff6b6b;
}

布局示例

网格布局

<template><ProGoodsList :goods-list="goodsList" layout="grid" />
</template>

列表布局

<template><ProGoodsList :goods-list="goodsList" layout="list" />
</template>

商品列表组件

<template><view class="goods"><view v-if="list.length > 0" class="scroll-wrapper"><scroll-view:scroll-top="scrollTop":scroll-y="scrollY":class="scrollY && 'scroll-Y'"@scrolltolower="onScrolltolower"><view class="goods-card-wrapper"><viewv-for="(item, index) in list":key="index"@click.stop="itemClick(item)"class="card-item"><view class="pro-good-card"><view class="img-wrapper-A" :class="cardType === 'B' && 'img-wrapper-B'"><image class="pro-good-img" mode="widthFix" :src="item.picUrl" alt="" /></view><view class="pro-good-info"><view class="first-title">{{ item.name }}</view><viewv-if="item.goodsDes"class="sec-title-A":class="cardType === 'B' && 'sec-title-A'">{{ item.goodsDes }}</view><view class="pro-good-price-A" :class="cardType === 'B' && 'pro-good-price-B'"><view><text v-if="priceInfo.unit" class="price-unit">{{ priceInfo.unit }}</text><text class="retail-price">{{ item.countPrice }}</text><text v-if="priceInfo.des" class="price-des">{{ priceInfo.des }}</text></view><view v-if="item.counterPrice" class="counter-price">¥{{ item.counterPrice }}</view></view></view></view></view></view></scroll-view></view><view v-else><imageclass="empty-img"src="https://static.wxb.com.cn/frontEnd/images/benz-mp/goods-empty.png"></image><view class="empty-text">暂无商品</view></view></view>
</template>
<script setup>import { ref, computed } from "vue";const props = defineProps({// 列表数据list: {type: Array,required: true,default: () => [],},// 卡片类型:A/BcardType: {type: String,default: "A",},// 卡片样式goodsStyle: {type: Object,default: () => {return {};},},// 价格相关的信息priceInfo: {type: Object,default: () => {return {unit: "¥",des: "起",};},},// 是否开启上拉加载scrollY: {type: Boolean,default: false,},//  滚动高度scrollHeight: {type: Number,default: 0,},});const scrollHeight = props.scrollHeight;const _goodsStyle = computed(() => {const options = {borderRadius: "16rpx", // 卡片圆角bgColor: props.cardType === "A" ? "#fff" : "rgba(255, 255, 255, 0.74)", // 卡片背景颜色//一级标题样式firstTitle: {fontSize: "28rpx",color: "#333",fontFamily: "PingFang SC, sans-serif",},//二级标题样式secondTitle: {fontSize: "22rpx",color: "#666",fontFamily: "PingFang SC, sans-serif",},priceColor: "#FF4D3B", // 价格字体颜色columnGap: "24rpx", // 列间距rowGap: "24rpx", // 行间距};return Object.assign(options, props.goodsStyle);});// 卡片圆角const borderRadius = _goodsStyle.value.borderRadius;// 一级标题样式const { fontSize: ffs, color: fc, fontFamily: ffm } = _goodsStyle.value.firstTitle;// 二级标题样式const { fontSize: sfs, color: sc, fontFamily: sfm } = _goodsStyle.value.secondTitle;// 价格颜色const priceColor = _goodsStyle.value.priceColor;// 卡片背景色const bgColor = _goodsStyle.value.bgColor;// 列间距const columnGap = _goodsStyle.value.columnGap;// 行间距const rowGap = _goodsStyle.value.rowGap;// 点击事件const emits = defineEmits(["itemClick", "scroll"]);const itemClick = (item) => {emits("itemClick", item.id);};const onScrolltolower = () => {console.log("上拉加载");emits("scroll");};
</script>
<style scoped lang="scss">@import '../base.scss';// 用于数字的特殊字体@font-face {font-family: "TCloudNumberRegular";src: url("./fonts/TCloudNumber-Regular.ttf") format("truetype"),url("./fonts/TCloudNumber-Regular.ttf") format("woff2");}.goods {text-align: center;height: v-bind(scrollHeight);.scroll-wrapper {height: 100%;.scroll-Y {height: 100%;}.goods-card-wrapper {column-gap: v-bind(columnGap);column-count: 2;.card-item {margin-bottom: 24rpx;break-inside: avoid; //避免子元素内容被截取.pro-good-card {width: 100%;background: v-bind(bgColor);border-radius: v-bind(borderRadius);overflow: hidden;.img-wrapper-A {padding: 12rpx 12rpx 0 12rpx;.pro-good-img {display: block;width: 100%;border-radius: 12rpx;}}.img-wrapper-B {padding: 0;.pro-good-img {display: block;width: 100%;border-radius: 0;}}.pro-good-info {padding: 0rpx 20rpx 28rpx 20rpx;}.first-title {font-size: v-bind(ffs);color: v-bind(fc);font-family: v-bind(ffm);font-weight: 500;line-height: 36rpx;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 2;margin-top: 20rpx;text-align: left;}.first-title-B {margin-top: 10rpx;}.sec-title-A {font-size: v-bind(sfs);color: v-bind(sc);font-family: v-bind(sfm);line-height: 32rpx;margin-top: 8rpx;overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;text-align: left;}.sec-title-B {margin-top: 4rpx;}.pro-good-price-A {display: flex;align-items: baseline;margin-top: 24rpx;.price-unit {font-size: 20rpx;font-family: "TCloudNumberRegular";font-weight: 400;color: v-bind(priceColor);line-height: 24rpx;}.price-des {font-size: 20rpx;font-family: PingFang SC, sans-serif;font-weight: 500;color: v-bind(priceColor);line-height: 28rpx;margin-left: 4rpx;}.retail-price {font-size: 40rpx;color: v-bind(priceColor);line-height: 44rpx;font-family: "TCloudNumberRegular";vertical-align: middle;}.counter-price {font-size: 24rpx;text-decoration: line-through;margin-left: 12rpx;color: #cecece;font-family: "TCloudNumberRegular";}}.pro-good-price-B {margin-top: 20rpx;}}}}}}
</style>

http://www.ppmy.cn/devtools/152871.html

相关文章

Unreal Engine 5 C++ Advanced Action RPG 十一章笔记

第十一章 In Game Widgets 本章节就是做UI2-Template Button Widget 这章节创建不同的UI 结束UI胜利UI暂停菜单主菜单加载UI新建一个按钮小组件作为模版 3-Pause Menu Template Button 继续做更多模版UI 4-Lose Screen(游戏失败UI) 做失败的UI 之前按钮模版的调度程序就在这起…

Python中采用.add_subplot绘制子图的方法简要举例介绍

Python中采用.add_subplot绘制子图的方法简要举例介绍 目录 Python中采用.add_subplot绘制子图的方法简要举例介绍一、Python中绘制子图的方法1.1 add_subplot函数1.2 基本语法&#xff08;1&#xff09;add_subplot的核心语法&#xff08;2&#xff09;add_subplot在中编程中的…

【深度学习】常见模型-卷积神经网络(Convolutional Neural Networks, CNN)

卷积神经网络&#xff08;CNN&#xff09; 概念简介 卷积神经网络&#xff08;Convolutional Neural Networks, CNN&#xff09;是一种专门用于处理数据具有网格状拓扑结构&#xff08;如图像、语音&#xff09;的深度学习模型。它通过卷积操作从输入数据中提取局部特征&…

3D可视化定制:开启个性化购物新时代,所见即所得

在当前的数字化浪潮中&#xff0c;3D可视化产品定制正悄然革新消费者的购物旅程与企业的营销战略。相较于众多仍局限于二维平面的在线定制服务&#xff0c;3D可视化产品定制为消费者解锁了一个直观互动、高度个性化的定制新天地&#xff0c;赋予他们沉浸式的购物享受。 通过3D…

【深度学习】傅里叶变换

[toc]深度学习中的傅里叶变换 傅里叶变换 傅里叶变换在深度学习中有着广泛的应用&#xff0c;尤其是在信号处理、图像处理和自然语言处理等领域。 1. 傅里叶变换基础 傅里叶变换是一种将信号从时域转换到频域的数学工具。对于连续信号&#xff0c;傅里叶变换定义为&#xf…

fyne 选项卡设计

用户界面的设计至关重要&#xff0c;它直接影响着用户体验。选卡设计作为一种常见的界面布局方式&#xff0c;能够有效地组织和展示信息&#xff0c;使用户能够方便快捷地浏览和操作。 Fyne 是一个用 Go 语言编写的跨平台 GUI 框架&#xff0c;它提供了丰富的组件和功能&#…

Oracle审计

审计是监控选定的用户数据库操作的过程 审计的目的&#xff1a; 调查可疑的数据库活动&#xff1a; 审计可以帮助检测和跟踪潜在的 security breaches、未授权的访问尝试或其他异常行为。通过分析审计日志&#xff0c;可以确定可疑活动的来源、时间、频率和影响。 收集特定数…

【Day24 LeetCode】贪心Ⅱ

一、贪心Ⅱ 1、买卖股票的最佳时机 II 122 这题第一想法是使用动态规划做&#xff0c;每天有两个状态&#xff0c;持有股票和非持有股票&#xff0c;每次计算这两个状态下的最优值。 class Solution { public:int maxProfit(vector<int>& prices) {//表示当前 没有…