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
相关产品推荐
相关产品推荐

