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

Angular 2中通过服务实现选品加入购物车失败求助

解决Angular组件与服务间数据传递的购物车功能问题

我帮你梳理下问题出在哪,以及怎么一步步修复:

1. 核心问题:服务未实现单例共享

你在每个组件的providers数组里声明了服务(比如BuyGameComponent里的gameService、CartComponent里的cartService),这会导致每个组件创建独立的服务实例,数据完全隔离,自然没法实现跨组件的购物车同步。

修复方案:
把服务改为根级注入(Angular 6+推荐方式),确保整个应用只有一个服务实例:

// cart.service.ts
import { Injectable } from "@angular/core";
import { cartModel } from "./cart.model";
import { EventEmitter } from "@angular/core";
import { Subscription } from 'rxjs';

@Injectable({ providedIn: 'root' }) // 根注入,实现单例
export class cartService{
  cartChanged = new EventEmitter<cartModel[]>(); // 修正为数组类型
  cart: cartModel[] = [
    new cartModel('Batman','Batman is a cool game','https://images-na.ssl-images-amazon.com/images/I/91lu5KHSm3L._SY445_.jpg'),
    new cartModel('Gta 5','online game of GTA','https://www.rockstargames.com/V/img/global/order/mobile-cover.jpg')
  ];

  getCartItem(){
    return this.cart.slice();
  }

  addItem(cartItem: cartModel){ // 改为接收单个购物车项
    this.cart.push(cartItem);
    this.cartChanged.emit(this.cart.slice());
  }
}
// game.service.ts
import { gameBuy } from "./buygame.model";
import { Injectable } from "@angular/core";
import { cartService } from "./cart.service";
import { cartModel } from "./cart.model";

@Injectable({ providedIn: 'root' })
export class gameService{
  private gameServ: gameBuy[] = [
    new gameBuy('batman',' Batmobile and enhancements to signature features',"https://www.geek.com/wp-content/uploads/2016/02/batmans-625x352.jpg"),
    new gameBuy('GTA 5', "PlayStation 3 or Xbox 360 will be able to transfer their current Grand Theft Auto Online characters and progression to their choice of PlayStation 4 Xbox One or PC", "https://vignette.wikia.nocookie.net/gtawiki/images/7/76/CoverArt-GTAV.png/revision/latest?cb=20130826184215")
  ];

  constructor(private cartService: cartService){}

  getBuyingList(){
    return this.gameServ.slice();
  }

  addItemToCart(game: gameBuy){ // 改为接收单个游戏项
    // 转换为购物车模型(匹配cartModel的结构)
    const cartItem = new cartModel(game.names, game.desc, game.getImg);
    this.cartService.addItem(cartItem);
  }
}

然后移除所有组件中的providers配置,比如BuyGameComponent和CartComponent里的providers: [xxxService]都删掉。

2. 点击按钮传递的是整个列表,而非当前商品

你当前的onAddToCart()没有传递点击的单个商品,而是直接传了整个this.buy列表,导致一点击就把所有游戏都加入购物车。

修复方案:
修改购买组件的TS和HTML,传递当前点击的游戏项:

// buy-game.component.ts
@Component({
  selector: 'app-buy-game',
  templateUrl: './buy-game.component.html',
  styleUrls: ['./buy-game.component.css']
})
export class BuyGameComponent implements OnInit {
  buy: gameBuy[]; // 不需要@Input,因为是从服务获取数据

  constructor(private service: gameService) { }

  ngOnInit() {
    this.buy = this.service.getBuyingList();
  }

  onAddToCart(selectedGame: gameBuy){ // 接收当前选中的游戏
    this.service.addItemToCart(selectedGame);
  }
}
<!-- buy-game.component.html -->
<div class="col-xs-6">
  <a class="list-group-item clearfix" style="background-color:rgb(3, 0, 48)" *ngFor="let buying of buy">
    <div class="pull-left" style="max-width:350px">
      <h5 style="color:white">{{buying.names}}</h5>
      <p style="color:white">{{buying.desc}}</p>
      <!-- 传递当前循环的buying项 -->
      <button class="btn btn-danger pull-left" (click)="onAddToCart(buying)">Add To Cart</button>
    </div>
    <div>
      <span class="pull-right">
        <img [src]="buying.getImg" alt="image not loaded" class="img-responsive" style="max-height:100px">
      </span>
    </div>
  </a>
</div>

3. 购物车组件未订阅数据更新

你的CartComponent只在ngOnInit里获取一次初始购物车数据,当购物车内容变化时不会自动刷新。需要订阅服务的cartChanged事件。

修复方案:

// cart.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { cartModel } from './cart.model';
import { cartService } from './cart.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-cart',
  templateUrl: './cart.component.html',
  styleUrls: ['./cart.component.css']
})
export class CartComponent implements OnInit, OnDestroy {
  cart: cartModel[];
  private cartSubscription: Subscription;

  constructor(private service: cartService) { }

  ngOnInit() {
    this.cart = this.service.getCartItem();
    // 订阅购物车变化事件,实时更新数据
    this.cartSubscription = this.service.cartChanged.subscribe(
      (updatedCart: cartModel[]) => {
        this.cart = updatedCart;
      }
    );
  }

  // 组件销毁时取消订阅,避免内存泄漏
  ngOnDestroy() {
    this.cartSubscription.unsubscribe();
  }
}

最后验证

做完这些修改后,点击任意游戏的"Add To Cart"按钮,对应的商品就会正确加入购物车,并且购物车组件会实时更新显示内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:22:53