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

单按钮实现商品收藏与取消收藏功能的技术咨询

实现收藏按钮的添加/移除双向功能

嘿,我来帮你搞定这个收藏按钮的双向操作!咱们可以结合**本地存储(localStorage)**来持久化收藏数据,同时复用你现有的样式切换逻辑,让同一个按钮完美实现「添加收藏」和「取消收藏」的切换。下面是修改后的完整代码,之后我会拆解每个关键部分的作用:

修改后的完整代码

HTML 部分

<head> 
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> 
</head> 
<body> 
  <div class="containerOfFavorite"> 
    <!-- 给商品卡片添加唯一ID,方便识别不同商品 -->
    <div class="cardOfFavorite" data-id="1" style="border: 5px solid red; width:250px; display:flex; flex-direction:column; justify-content:center; align-items: center; padding: 7px; position: relative; cursor: pointer;"> 
      <span class="material-icons HeartSpanImage active delete-itemFavorite" id="HeartSpanImage" data-name="CORSAIR ONE i300" data-price="1.50"> favorite </span> 
      <img class="amico" src="https://www.corsair.com/de/de/medias/sys_master/images/images/h1d/he3/9950073159710/CS-9020031-PE/Gallery/CORSAIR_ONE_i300_2022_01/-CS-9020031-PE-Gallery-CORSAIR-ONE-i300-2022-01.png_515Wx515H" alt="CORSAIR ONE i300" width="150px"> 
      <img src="" class="imageHide" id="imageHide"></img> 
      <h3 style="color: red;">CORSAIR ONE i300</h3> 
      <label style="color:grey;" for="">$1.50</label> 
    </div>
    <!-- 可添加更多测试商品卡片 -->
    <div class="cardOfFavorite" data-id="2" style="border: 5px solid blue; width:250px; display:flex; flex-direction:column; justify-content:center; align-items: center; padding: 7px; position: relative; cursor: pointer; margin-top:20px;"> 
      <span class="material-icons HeartSpanImage delete-itemFavorite" data-name="Test Product" data-price="2.99"> favorite </span> 
      <img class="amico" src="https://picsum.photos/200" alt="Test Product" width="150px"> 
      <img src="" class="imageHide" id="imageHide"></img> 
      <h3 style="color: blue;">Test Product</h3> 
      <label style="color:grey;" for="">$2.99</label> 
    </div>
  </div>
</body>

CSS 部分(保持原有样式无需修改)

body{ display: flex; justify-content: center; } 
.cardOfFavorite{ position: relative; } 
.HeartSpanImage{ margin-right: 5px; padding: 10px 0; font-size: 35px; color: grey; } 
.HeartSpanImage:active{ transform: scale(0.9); } 
.HeartSpanImage.active{ color: red; } 
.HeartSpanImage:focus> .imageHide{ display: block; } 
.HeartSpanImage:hover, .HeartSpanImage:focus{ color: red; transform: scale(1.1); }

JavaScript 部分

// 从本地存储获取收藏列表,无数据则返回空数组
function getFavorites() {
  return JSON.parse(localStorage.getItem('favorites')) || [];
}

// 将收藏列表保存到本地存储
function saveFavorites(favorites) {
  localStorage.setItem('favorites', JSON.stringify(favorites));
}

// 初始化页面:把已收藏的商品按钮设置为active状态
function initFavorites() {
  const favorites = getFavorites();
  const heartButtons = document.querySelectorAll('.HeartSpanImage');
  
  heartButtons.forEach(button => {
    const productId = button.closest('.cardOfFavorite').dataset.id;
    if (favorites.some(item => item.id === productId)) {
      button.classList.add('active');
    }
  });
}

// 给所有收藏按钮绑定点击事件
document.querySelectorAll('.HeartSpanImage').forEach(button => {
  button.addEventListener('click', function() {
    // 获取当前商品的完整信息
    const card = this.closest('.cardOfFavorite');
    const productInfo = {
      id: card.dataset.id,
      name: this.dataset.name,
      price: this.dataset.price,
      image: card.querySelector('.amico').src
    };
    
    let favorites = getFavorites();
    
    // 判断当前商品是否已在收藏列表中
    const isFavorite = favorites.some(item => item.id === productInfo.id);
    
    if (isFavorite) {
      // 已收藏:从列表移除,同时移除active类
      favorites = favorites.filter(item => item.id !== productInfo.id);
      this.classList.remove('active');
      console.log(`已移除收藏:${productInfo.name}`);
    } else {
      // 未收藏:添加到列表,同时添加active类
      favorites.push(productInfo);
      this.classList.add('active');
      console.log(`已添加收藏:${productInfo.name}`);
    }
    
    // 保存更新后的收藏列表
    saveFavorites(favorites);
    
    // 可扩展:调用渲染函数展示收藏列表
    // renderFavoriteList();
  });
});

// 页面加载完成后初始化收藏状态
document.addEventListener('DOMContentLoaded', initFavorites);

关键功能拆解

  1. 本地存储持久化

    • 用localStorage保存收藏列表,页面刷新或关闭后数据不会丢失。
    • getFavorites()和saveFavorites()封装了读写逻辑,让代码更简洁易维护。
  2. 商品唯一标识

    • 给每个商品卡片添加data-id属性,避免因商品名称/价格重复导致的判断错误,确保每个商品能被精准识别。
  3. 点击事件逻辑

    • 点击按钮时先获取商品的完整信息(ID、名称、价格、图片)。
    • 通过some()方法判断商品是否已在收藏列表:
      • 已存在:用filter()移除该商品,同时移除按钮的active类(恢复灰色)。
      • 不存在:把商品信息加入列表,同时添加active类(变成红色)。
    • 最后将更新后的列表保存回本地存储。
  4. 页面初始化

    • 页面加载完成后调用initFavorites(),自动把已收藏的商品按钮设为红色active状态,保证状态一致性。

你可以根据需求扩展功能,比如添加「我的收藏」页面,调用getFavorites()获取数据后渲染展示~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:12:38