VueJS中单个商品项Hover仅显示自身价格的问题
问题解决:Vue循环项悬停时仅显示当前商品价格
问题原因
你当前使用了一个全局的hover布尔变量,所有循环渲染的<li>都绑定这个变量。鼠标悬停任意商品时,hover被设为true,导致所有商品的价格同时显示;鼠标离开时hover设为false,所有价格又同时隐藏。
解决方案
方案1:给每个商品单独维护hover状态
在加载Firebase数据时,给每个商品对象添加响应式的isHover属性,让每个商品的悬停状态独立可控。
修改后的script代码:
import { ref, onMounted } from 'vue' import { collection, onSnapshot } from 'firebase/firestore' import { db } from '@/firebase/config' // 替换为你的Firebase配置路径 setup() { const products = ref([]) onMounted(() => { onSnapshot(collection(db, "malesneakers"), (querySnapshot) => { const maleProducts = [] querySnapshot.forEach((doc) => { const mlproducts = { id: doc.id, imageSrc: doc.data().imageSrc, name: doc.data().name, price: doc.data().price, cheapestat: doc.data().cheapestat, svgSrc: doc.data().svgSrc, href: doc.data().href, isHover: ref(false) // 给每个商品添加独立的响应式悬停状态 } maleProducts.push(mlproducts) }) products.value = maleProducts }) }) return { products } }
修改模板中的事件绑定和显示判断:
<div class="relative w-full pb-6 -mb-6 overflow-x-auto scrollbar-hide"> <ul role="list" class="mx-4 inline-flex space-x-0 gap-2 sm:mx-6 lg:mx-0 lg:space-x-0 lg:grid lg:grid-cols-6 lg:gap-x-4"> <li v-if="products.length" v-for="product in products" :key="product.id" @mouseenter="product.isHover = true" @mouseleave="product.isHover = false" class="w-44 inline-flex border hover:border-black rounded-lg p-4 lg:w-auto"> <div class="group relative"> <div class="w-[70%] lg:w-[55%] bg-gray-white overflow-hidden"> <img :src="product.imageSrc" :alt="product.imageAlt" class="w-full h-20 overflow-hidden object-center object-contain" /> </div> <div class="mt-2"> <h3 class="mt-1 font-rubikreg h-11 overflow-hidden text-xs lg:text-base uppercase text-gray-900"> <a :href="product.href"> <span class="absolute inset-0" /> {{ product.name }} </a> </h3> <p class="mt-3 lg:mt-6 font-rubiklight uppercase text-xs lg:text-sm text-gray-900"> Cheapest At </p> <p class="mt-1 font-rubikreg underline-offset-2 underline uppercase text-xs lg:text-sm text-gray-900"> {{ product.cheapestat }} </p> <p v-if="product.isHover" class="mt-5 text-2xl uppercase font-rubik text-gray-900"> <span class="text-xs">From</span> A${{ product.price }} </p> </div> </div> </li> </ul> </div>
方案2:维护当前悬停的商品ID
通过一个变量存储当前悬停商品的ID,模板中判断当前商品ID是否匹配该变量,从而控制价格显示。
修改后的script代码:
import { ref, onMounted } from 'vue' import { collection, onSnapshot } from 'firebase/firestore' import { db } from '@/firebase/config' setup() { const products = ref([]) const hoveredProductId = ref(null) // 存储当前悬停商品的ID onMounted(() => { onSnapshot(collection(db, "malesneakers"), (querySnapshot) => { const maleProducts = [] querySnapshot.forEach((doc) => { const mlproducts = { id: doc.id, imageSrc: doc.data().imageSrc, name: doc.data().name, price: doc.data().price, cheapestat: doc.data().cheapestat, svgSrc: doc.data().svgSrc, href: doc.data().href, } maleProducts.push(mlproducts) }) products.value = maleProducts }) }) return { products, hoveredProductId } }
修改模板中的事件绑定和显示判断:
<div class="relative w-full pb-6 -mb-6 overflow-x-auto scrollbar-hide"> <ul role="list" class="mx-4 inline-flex space-x-0 gap-2 sm:mx-6 lg:mx-0 lg:space-x-0 lg:grid lg:grid-cols-6 lg:gap-x-4"> <li v-if="products.length" v-for="product in products" :key="product.id" @mouseenter="hoveredProductId = product.id" @mouseleave="hoveredProductId = null" class="w-44 inline-flex border hover:border-black rounded-lg p-4 lg:w-auto"> <div class="group relative"> <div class="w-[70%] lg:w-[55%] bg-gray-white overflow-hidden"> <img :src="product.imageSrc" :alt="product.imageAlt" class="w-full h-20 overflow-hidden object-center object-contain" /> </div> <div class="mt-2"> <h3 class="mt-1 font-rubikreg h-11 overflow-hidden text-xs lg:text-base uppercase text-gray-900"> <a :href="product.href"> <span class="absolute inset-0" /> {{ product.name }} </a> </h3> <p class="mt-3 lg:mt-6 font-rubiklight uppercase text-xs lg:text-sm text-gray-900"> Cheapest At </p> <p class="mt-1 font-rubikreg underline-offset-2 underline uppercase text-xs lg:text-sm text-gray-900"> {{ product.cheapestat }} </p> <p v-if="hoveredProductId === product.id" class="mt-5 text-2xl uppercase font-rubik text-gray-900"> <span class="text-xs">From</span> A${{ product.price }} </p> </div> </div> </li> </ul> </div>
说明
方案2更轻量,无需修改商品数据结构;方案1将状态与商品绑定,逻辑更独立,适合复杂场景,可根据需求选择。
内容的提问来源于stack exchange,提问作者chrisjarn
相关产品推荐
相关产品推荐

