Angular购物车总价无法在页面更新问题求助
Angular购物车总价无法更新页面显示问题分析与解决
问题描述
开发Angular简易购物网站时,添加商品到购物车后,商品名称和价格能正常显示,但计算总价的函数返回的结果无法更新页面——控制台能输出正确总价,页面绑定的总价却始终是初始值。
相关代码
Service.ts
import { Injectable } from '@angular/core'; import { basketModel } from './models/basket.model'; import { ProductModel } from './models/product.model'; @Injectable({ providedIn: 'root' }) export class DataService { baskets: basketModel[]= []; addBasket(product2: ProductModel){ let cartModel= new basketModel(product2.name,1,product2.price) this.baskets.push(cartModel) console.log(this.baskets) this.totalPrice() } constructor() { } getBasketList():basketModel[]{ return this.baskets; } totalPrice(){ let total=0 for(let i of this.baskets){ total=total+i.price console.log(total) } return total } }
组件代码
@Component({ selector: 'app-basket', templateUrl: './basket.component.html', styleUrls: ['./basket.component.scss'], }) export class BasketComponent implements OnInit { baskets: basketModel[]; total2: number; constructor(dataservice: DataService) { this.baskets = dataservice.baskets; this.total2=dataservice.totalPrice() } ngOnInit(): void { } }
HTML页面代码
<tbody> <tr *ngFor="let i of baskets"> <td>{{i.product}}</td> <td>{{i.quantity}}</td> <td>{{i.price}}</td> <td></td> </tr> </tbody> <tfoot> <tr> <th>Total</th> <td>{{total2}}</td> <td></td> </tr> </tfoot>
问题原因
total2仅初始化一次:组件的total2变量只在构造函数中赋值了一次,之后添加商品时没有重新计算并更新该变量,页面绑定的total2始终保持初始值(购物车为空时的0)。- Service未通知组件更新:虽然
addBasket方法调用了totalPrice(),但该调用仅在控制台输出计算结果,没有将新的总价传递给组件更新total2。 - 变更检测机制限制:Angular会自动检测数组内容变化并更新
*ngFor列表,但total2是独立变量,不会自动跟随购物车数组的变化重新计算。
解决方案
方案1:手动触发总价更新(简单直接)
修改组件,将Service注入改为private,并在购物车变化时重新计算总价:
@Component({ selector: 'app-basket', templateUrl: './basket.component.html', styleUrls: ['./basket.component.scss'], }) export class BasketComponent implements OnInit { baskets: basketModel[]; total2: number; constructor(private dataservice: DataService) { this.baskets = dataservice.getBasketList(); this.total2 = dataservice.totalPrice(); } ngOnInit(): void { } // 调用此方法更新总价(比如在添加商品的按钮点击事件后调用) updateTotal() { this.total2 = this.dataservice.totalPrice(); } }
方案2:用Observable实现响应式更新(推荐)
通过BehaviorSubject让Service推送购物车变化,组件订阅后自动更新总价:
修改Service.ts
import { Injectable } from '@angular/core'; import { basketModel } from './models/basket.model'; import { ProductModel } from './models/product.model'; import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataService { private basketsSubject = new BehaviorSubject<basketModel[]>([]); baskets$ = this.basketsSubject.asObservable(); addBasket(product2: ProductModel){ const currentBaskets = this.basketsSubject.value; const cartModel = new basketModel(product2.name, 1, product2.price); currentBaskets.push(cartModel); this.basketsSubject.next([...currentBaskets]); // 发送新数组引用触发变更 } getBasketList(): basketModel[] { return this.basketsSubject.value; } totalPrice(): number { let total = 0; for(let i of this.basketsSubject.value){ total += i.price; } return total; } }
修改组件代码
@Component({ selector: 'app-basket', templateUrl: './basket.component.html', styleUrls: ['./basket.component.scss'], }) export class BasketComponent implements OnInit { baskets$ = this.dataservice.baskets$; total2: number; constructor(private dataservice: DataService) { this.total2 = dataservice.totalPrice(); } ngOnInit(): void { this.dataservice.baskets$.subscribe(() => { this.total2 = this.dataservice.totalPrice(); }); } }
修改HTML代码
<tbody> <tr *ngFor="let i of baskets$ | async"> <td>{{i.product}}</td> <td>{{i.quantity}}</td> <td>{{i.price}}</td> <td></td> </tr> </tbody> <tfoot> <tr> <th>Total</th> <td>{{total2}}</td> <td></td> </tr> </tfoot>
方案3:HTML直接调用Service方法(快速实现)
将Service设为public,HTML中直接调用totalPrice(),Angular会在变更检测时自动更新:
@Component({ selector: 'app-basket', templateUrl: './basket.component.html', styleUrls: ['./basket.component.scss'], }) export class BasketComponent implements OnInit { baskets: basketModel[]; constructor(public dataservice: DataService) { this.baskets = dataservice.getBasketList(); } ngOnInit(): void { } }
<tfoot> <tr> <th>Total</th> <td>{{dataservice.totalPrice()}}</td> <td></td> </tr> </tfoot>
内容的提问来源于stack exchange,提问作者Atilla Ertürk
相关产品推荐
相关产品推荐

