Vue Nuxt Tailwind中动态设置商品贴纸颜色的实现方法
问题:动态设置商品贴纸样式及布局实现
当前代码
<template> <div> <!-- title --> <section class="pt-4 w-fit mx-32 grid grid-cols-1 lg:grid-cols-4 md:grid-cols-2 justify-items-center justify-center gap-y-20 gap-x-20 mt-4 mb-5"> <tr v-for="product in products" :key="product.id"> <div class="w-56 bg-white rounded-xl duration-500 hover:scale-105 hover:shadow-xl"> <div v-for="(image, index) in product.images" :key="image.url"> <div v-if="index === 0"> <img :src="image.url" alt="" class="h-[14rem] w-72 object-cover rounded-xl"> </div> </div> <div class="px-2 py-3 w-60"> <p class="text-lg font-semibold text-black truncate block capitalize">{{ product.name }}</p> </div> <stars :numStars=product.stars :numReviews=product._count.reviews></stars> <div class="flex items-center"> <p class="pl-2 text-lg font-bold text-black cursor-auto my-1">R$ {{ product.price }}</p> <div v-for="(sticker, index) in product.stickers" :key="index"> <p>Sticker name: {{ sticker.name }}</p> <p>Sticker discount: {{ sticker.discount }}</p> <div :title=sticker.color></div> <p class="">Sticker color: {{ sticker.color }}</p> <p>Sticker text color: {{ sticker.textColor }}</p> </div> </div> </div> </tr> </section> </div> </template>
数据说明
通过API获取商品数据,当前仅最后一个商品带有贴纸,贴纸的sticker-color和text-color为测试用随机值。
需求
利用返回的sticker-color和text-color动态设置贴纸样式,每个商品最多包含两个贴纸,目标布局为贴纸叠加在商品图片角落的样式。
解决方案
1. 基础结构修正
首先注意到代码中用了<tr>标签但未包裹在<table>内,属于无效HTML结构,建议替换为<div>:
<!-- 替换原<tr>标签 --> <div v-for="product in products" :key="product.id">
2. 单贴纸实现方案
将贴纸定位在商品图片左上角,通过Vue动态样式绑定实现颜色设置:
<template> <div> <section class="pt-4 w-fit mx-32 grid grid-cols-1 lg:grid-cols-4 md:grid-cols-2 justify-items-center justify-center gap-y-20 gap-x-20 mt-4 mb-5"> <div v-for="product in products" :key="product.id"> <!-- 相对定位容器,用于贴纸绝对定位 --> <div class="w-56 bg-white rounded-xl duration-500 hover:scale-105 hover:shadow-xl relative"> <div class="relative"> <!-- 直接取第一张图片,简化循环逻辑 --> <img :src="product.images[0]?.url" alt="" class="h-[14rem] w-72 object-cover rounded-xl"> <!-- 渲染单张贴纸 --> <div v-if="product.stickers.length > 0" class="absolute top-2 left-2 px-2 py-1 rounded text-xs font-bold" :style="{ backgroundColor: product.stickers[0].color, color: product.stickers[0].textColor }" > {{ product.stickers[0].name }} </div> </div> <div class="px-2 py-3 w-60"> <p class="text-lg font-semibold text-black truncate block capitalize">{{ product.name }}</p> </div> <stars :numStars="product.stars" :numReviews="product._count.reviews"></stars> <div class="flex items-center"> <p class="pl-2 text-lg font-bold text-black cursor-auto my-1">R$ {{ product.price }}</p> </div> </div> </div> </section> </div> </template>
3. 多贴纸(最多2个)实现方案
支持最多2个贴纸,分别定位在图片左上角和右上角:
<template> <div> <section class="pt-4 w-fit mx-32 grid grid-cols-1 lg:grid-cols-4 md:grid-cols-2 justify-items-center justify-center gap-y-20 gap-x-20 mt-4 mb-5"> <div v-for="product in products" :key="product.id"> <div class="w-56 bg-white rounded-xl duration-500 hover:scale-105 hover:shadow-xl relative"> <div class="relative"> <img :src="product.images[0]?.url" alt="" class="h-[14rem] w-72 object-cover rounded-xl"> <!-- 循环渲染最多2个贴纸 --> <div v-for="(sticker, index) in product.stickers.slice(0, 2)" :key="sticker.id || index" class="absolute px-2 py-1 rounded text-xs font-bold" :class="{ 'top-2 left-2': index === 0, 'top-2 right-2': index === 1 }" :style="{ backgroundColor: sticker.color, color: sticker.textColor }" > {{ sticker.name }} </div> </div> <div class="px-2 py-3 w-60"> <p class="text-lg font-semibold text-black truncate block capitalize">{{ product.name }}</p> </div> <stars :numStars="product.stars" :numReviews="product._count.reviews"></stars> <div class="flex items-center"> <p class="pl-2 text-lg font-bold text-black cursor-auto my-1">R$ {{ product.price }}</p> </div> </div> </div> </section> </div> </template>
关键实现要点
- 给商品图片容器设置
relative定位,让贴纸可通过absolute定位到角落 - 使用
:style动态绑定backgroundColor和color,对应API返回的贴纸颜色值 - 通过
:class根据贴纸索引设置不同位置(左上/右上) - 用
slice(0,2)限制最多渲染2个贴纸 - 直接取
product.images[0]?.url简化图片渲染逻辑
内容的提问来源于stack exchange,提问作者Pedro Souza
相关产品推荐
相关产品推荐

