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

Angular电商项目心愿单图标切换功能实现求助

问题分析

你遇到的核心问题:

  1. 使用**单个全局布尔值inWishList**控制所有商品的爱心状态,导致点击任意商品时所有图标同步切换。
  2. 直接通过document.querySelector('.fa-heart')操作DOM,只会选中页面第一个匹配元素,无法单独控制每个商品的图标。
  3. 页面加载时心愿单数据是异步获取的,你在ngOnInit中直接调用isInWishlist时,wishData还未加载完成,初始状态判断失效。
  4. 点击事件未实现状态切换逻辑,当前的isInWishlist函数既没正确判断状态,也没调用添加/移除心愿单的接口。
解决方案

以下是修改后的完整代码,分组件类和模板两部分:

1. 组件类修改 (home.component.ts)

import { Product } from './../../interfaces/data';
import { Data } from '../../interfaces/data';
import { Component } from '@angular/core';
import { OwlOptions } from 'ngx-owl-carousel-o';
import { ProductsService } from 'src/app/services/products.service';
import { ToastrService } from 'ngx-toastr';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent {
  products: any[] = [];
  // 用Set存储心愿单商品ID,查询存在性效率更高
  wishlistIds: Set<string> = new Set();

  constructor(
    private _ProductsService: ProductsService, 
    private toastr: ToastrService
  ) { }

  ngOnInit(): void {
    this.getProducts();
    this.getWishlist();
  }

  getWishlist() {
    this._ProductsService.getWishList().subscribe({
      next: (res) => {
        // 提取心愿单商品ID存入Set
        this.wishlistIds = new Set(res.data.map(item => item._id));
      }
    });
  }

  getProducts() {
    this._ProductsService.getProducts().subscribe({
      next: (res) => {
        this.products = res.data;
      }
    })
  }

  // 判断单个商品是否在心愿单中
  isProductInWishlist(productId: string): boolean {
    return this.wishlistIds.has(productId);
  }

  // 切换商品心愿单状态
  toggleWishlist(productId: string) {
    if (this.isProductInWishlist(productId)) {
      // 已在心愿单,执行移除操作
      this._ProductsService.removeWishlistItemUser(productId).subscribe({
        next: (res) => {
          this.wishlistIds.delete(productId);
          this.toastr.error('商品已从心愿单移除', res.status);
        }
      });
    } else {
      // 不在心愿单,执行添加操作
      this._ProductsService.addWishList(productId).subscribe({
        next: (res) => {
          this.wishlistIds.add(productId);
          this.toastr.success('商品已加入心愿单', res.status);
        }
      });
    }
  }
}

关键修改说明:

  • 替换全局inWishList变量为wishlistIds集合,每个商品的状态由自身ID是否在集合中决定,避免全局状态污染。
  • 移除直接操作DOM的代码,改用Angular的状态判断逻辑控制样式。
  • 新增toggleWishlist方法,统一处理点击事件:先判断当前状态,再调用对应接口,最后更新集合并提示用户。
  • 修正异步数据加载逻辑,心愿单数据返回后直接更新集合,页面自动同步状态。

2. 模板修改 (home.component.html)

<div class="container">
  <div class="row">
    <div class="col-md-3 overflow-hidden" *ngFor="let product of products">
      <div class="product px-2">
        <button class="btn" (click)="toggleWishlist(product._id)">
          <i class="fa-heart" 
             [class.fa-solid]="isProductInWishlist(product._id)"
             [class.fa-regular]="!isProductInWishlist(product._id)">
          </i>
        </button>
        <a [routerLink]="['/productsDetailes',product._id]">
          <img [src]="product.imageCover" class="w-100 rounded-1" alt="">
          <span class="text-main fw-bold font-sm">{{product.category.name}}</span>
          <h3 class="fs-6 my-1 text-dark">{{product.title.split(' ').slice(0,2).join(' ')}}</h3>
          <div class="d-flex justify-content-between align-products-center font-sm">
            <span class="text-muted ">{{product.price}} EGP</span>
            <span><i class="fa-solid fa-star rating-color"></i> {{product.ratingsAverage}}</span>
          </div>
        </a>
        <button (click)="addToCart(product._id)" class="btn bg-main text-white my-2 w-100">+ Add</button>
      </div>
    </div>
  </div>
</div>

关键修改说明:

  • 按钮点击事件改为调用toggleWishlist(product._id),传递当前商品ID。
  • 爱心图标通过Angular动态类绑定控制:用isProductInWishlist判断单个商品状态,自动切换实心/空心样式。
  • 移除无效的AngularJS脚本引用(你使用的是Angular 2+,无需引入AngularJS)。
修改后效果
  1. 点击单个商品的爱心图标,仅该商品的样式切换,不会影响其他商品。
  2. 页面加载完成后,已在心愿单的商品自动显示实心爱心。
  3. 点击爱心时自动调用添加/移除接口,同步更新心愿单状态并提示用户。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 03:25:06