You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何控制仅点击的ProductCard显示Add to cart按钮的Spinner

解决单个ProductCard加载状态独立控制的问题

问题根源

你现在用的loading是在composable里全局共享的状态,所有ProductCard都会共用同一个值,所以只要有一个卡片触发加载,所有卡片都会切换成Spinner。

方案一:子组件单独维护loading状态

最简单的方式是让每个ProductCard自己管自己的加载状态,相互独立不干扰:

修改后的子组件代码

<template>
  <div id="productCart">
    <div>
      <NuxtLink :to="`/product/${item.slug}`" />
      <NuxtLink v-if="item.name" :to="`/product/${item.slug}`">
        <h5 id="productName" v-text="item.name" />
      </NuxtLink>
      <Button
        v-if="!loading"
        @click="handleAddToCart"
        v-text="$t('labels.buy')"
      />
      <Spinner v-else />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
const props = defineProps(['product'])
const item = props.product

// 每个卡片单独的loading状态,互不影响
const loading = ref(false)

async function handleAddToCart() {
  loading.value = true
  try {
    // 调用原来composable里的addToBuyCart方法
    await addToBuyCart({ product: item })
  } finally {
    // 不管接口成功失败,都把loading重置回去
    loading.value = false
  }
}
</script>

方案二:父组件统一管理加载中的产品ID

如果需要在父组件层面统一监控加载状态,可以用一个Set来记录当前正在加载的产品ID,再把状态传给对应子组件:

修改后的父组件代码

<template>
  <ProductCard
    v-for="product in products"
    :key="product.id"
    :product="product"
    :loading="loadingProductIds.has(product.id)"
    @add-to-cart="handleAddToCart(product)"
  />
</template>

<script setup>
import { ref } from 'vue'
const products = ref([]) // 你的产品列表数据
const loadingProductIds = ref(new Set())

async function handleAddToCart(product) {
  loadingProductIds.value.add(product.id)
  try {
    await addToBuyCart({ product })
  } finally {
    loadingProductIds.value.delete(product.id)
  }
}
</script>

修改后的子组件代码

<template>
  <div id="productCart">
    <div>
      <NuxtLink :to="`/product/${item.slug}`" />
      <NuxtLink v-if="item.name" :to="`/product/${item.slug}`">
        <h5 id="productName" v-text="item.name" />
      </NuxtLink>
      <Button
        v-if="!loading"
        @click="$emit('add-to-cart')"
        v-text="$t('labels.buy')"
      />
      <Spinner v-else />
    </div>
  </div>
</template>

<script setup>
const props = defineProps(['product', 'loading'])
const item = props.product
defineEmits(['add-to-cart'])
</script>

方案选择建议

  • 方案一:实现简单,不需要父组件改动,适合不需要父组件感知加载状态的场景。
  • 方案二:父组件统一管理状态,方便做全局统计或批量控制,适合需要在父层面处理加载逻辑的场景。

内容的提问来源于stack exchange,提问作者kozdro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 13:50:28