Javascript 当函数应该修改新数组时,对象的角度原始数组将被修改
我有一组导入到add-product.component.ts的产品 有一个功能,您可以将产品添加到名为basket的购物车中 car.service将做什么?将产品添加到名为basketItems的数组中。若产品已经存在于basketItems数组中,那个么它应该改变basketItem的条目 出于某种原因,篮子和产品都在发生变异,这导致了原产地产品显示在价格上发生变化,而只有篮子应该这样做 我是Angular的新手,我不确定在add-product.component.html中运行(单击)=“addToCart(product)”时是否传递了该产品的引用 添加product.component.html 产品系列Javascript 当函数应该修改新数组时,对象的角度原始数组将被修改,javascript,angular,typescript,Javascript,Angular,Typescript,我有一组导入到add-product.component.ts的产品 有一个功能,您可以将产品添加到名为basket的购物车中 car.service将做什么?将产品添加到名为basketItems的数组中。若产品已经存在于basketItems数组中,那个么它应该改变basketItem的条目 出于某种原因,篮子和产品都在发生变异,这导致了原产地产品显示在价格上发生变化,而只有篮子应该这样做 我是Angular的新手,我不确定在add-product.component.html中运行(单击)
<div class="d-flex justify-content-between flex-wrap">
<div *ngFor='let product of products' class="card mb-5" style="width: 20rem; height: 20rem">
<img style="object-fit: contain; margin-top: 5%" height="45%" src={{product.image}} [title]='product.name' class="card-img-top" alt={{product.name}}>
<div class="card-body">
<div class="mb-3">
<h5 class="card-title">{{product.name}}</h5>
<p class="card-text">{{product.description | slice:0:60}}...</p>
</div>
<a style="float: left" (click)="addToCart(product)" class="card-link text-primary">Add</a>
<p style="float: right">{{product.price | currency}}</p>
</div>
</div>
</div>
<div>
<div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Count</th>
<th scope="col">Product Name</th>
<th scope="col">Description</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let item of basket; index as itemId'>
<th scope="row"><button (click)="removeFromCart(itemId)">X</button></th>
<th scope="row">{{item.count}}</th>
<td>{{item.name}}</td>
<td>{{item.description | slice:0:20}}</td>
<td>{{item.price | currency}}</td>
</tr>
</tbody>
<thead>
<tr>
<th colspan="3" scope="col"></th>
<th scope="col">Total:</th>
<th scope="col">{{total | currency}}</th>
</tr>
</thead>
</table>
</div>
<button style="float: right" class="btn btn-primary">CHECK OUT</button>
</div>
import { Component, OnInit } from "@angular/core";
import { products } from "../products";
import { CartService } from "../cart.service";
@Component({
selector: "app-add-product",
templateUrl: "./add-product.component.html",
styleUrls: ["./add-product.component.css"]
})
export class AddProductComponent implements OnInit {
// Array of products to be displayed on screen for the user to add to the basket
products: object[] = products;
// The basket is an array of items that were added by the user when they click the add button for that product
basket: object[];
total: number;
constructor(private cartService: CartService) {}
addToCart(item) {
this.cartService.addToCart(item);
this.total = this.basket.reduce((total, item) => total + item.price, 0);
}
removeFromCart(index) {
this.cartService.removeFromCart(index);
this.basket = this.cartService.getItems();
this.total = this.basket.reduce((total, item) => total + item.price, 0);
}
ngOnInit() {
this.basket = this.cartService.getItems();
}
}
import { Injectable } from "@angular/core";
import { AngularFirestore } from "@angular/fire/firestore";
@Injectable()
export class CartService {
basketItems: object[] = [];
constructor(private db: AngularFirestore) {}
addToCart(product) {
// if product is already in the basket
// FIX ME basket should mutate and not the product
for (let i = 0; i < this.basketItems.length; i++) {
if (product === this.basketItems[i]) {
let originalPrice =
this.basketItems[i].price / this.basketItems[i].count;
this.basketItems[i].count = this.basketItems[i].count + 1;
this.basketItems[i].price = this.basketItems[i].price + originalPrice;
console.log("this should not mutate ===>", product, "but it does");
return;
}
}
this.basketItems.push(product);
}
removeFromCart(index) {
this.basketItems.splice(index, 1);
}
getItems() {
return this.basketItems;
}
clearCart() {
this.basketItems = [];
return this.basketItems;
}
}
购物车服务.ts
<div class="d-flex justify-content-between flex-wrap">
<div *ngFor='let product of products' class="card mb-5" style="width: 20rem; height: 20rem">
<img style="object-fit: contain; margin-top: 5%" height="45%" src={{product.image}} [title]='product.name' class="card-img-top" alt={{product.name}}>
<div class="card-body">
<div class="mb-3">
<h5 class="card-title">{{product.name}}</h5>
<p class="card-text">{{product.description | slice:0:60}}...</p>
</div>
<a style="float: left" (click)="addToCart(product)" class="card-link text-primary">Add</a>
<p style="float: right">{{product.price | currency}}</p>
</div>
</div>
</div>
<div>
<div>
<table class="table table-striped">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Count</th>
<th scope="col">Product Name</th>
<th scope="col">Description</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let item of basket; index as itemId'>
<th scope="row"><button (click)="removeFromCart(itemId)">X</button></th>
<th scope="row">{{item.count}}</th>
<td>{{item.name}}</td>
<td>{{item.description | slice:0:20}}</td>
<td>{{item.price | currency}}</td>
</tr>
</tbody>
<thead>
<tr>
<th colspan="3" scope="col"></th>
<th scope="col">Total:</th>
<th scope="col">{{total | currency}}</th>
</tr>
</thead>
</table>
</div>
<button style="float: right" class="btn btn-primary">CHECK OUT</button>
</div>
import { Component, OnInit } from "@angular/core";
import { products } from "../products";
import { CartService } from "../cart.service";
@Component({
selector: "app-add-product",
templateUrl: "./add-product.component.html",
styleUrls: ["./add-product.component.css"]
})
export class AddProductComponent implements OnInit {
// Array of products to be displayed on screen for the user to add to the basket
products: object[] = products;
// The basket is an array of items that were added by the user when they click the add button for that product
basket: object[];
total: number;
constructor(private cartService: CartService) {}
addToCart(item) {
this.cartService.addToCart(item);
this.total = this.basket.reduce((total, item) => total + item.price, 0);
}
removeFromCart(index) {
this.cartService.removeFromCart(index);
this.basket = this.cartService.getItems();
this.total = this.basket.reduce((total, item) => total + item.price, 0);
}
ngOnInit() {
this.basket = this.cartService.getItems();
}
}
import { Injectable } from "@angular/core";
import { AngularFirestore } from "@angular/fire/firestore";
@Injectable()
export class CartService {
basketItems: object[] = [];
constructor(private db: AngularFirestore) {}
addToCart(product) {
// if product is already in the basket
// FIX ME basket should mutate and not the product
for (let i = 0; i < this.basketItems.length; i++) {
if (product === this.basketItems[i]) {
let originalPrice =
this.basketItems[i].price / this.basketItems[i].count;
this.basketItems[i].count = this.basketItems[i].count + 1;
this.basketItems[i].price = this.basketItems[i].price + originalPrice;
console.log("this should not mutate ===>", product, "but it does");
return;
}
}
this.basketItems.push(product);
}
removeFromCart(index) {
this.basketItems.splice(index, 1);
}
getItems() {
return this.basketItems;
}
clearCart() {
this.basketItems = [];
return this.basketItems;
}
}
从“@angular/core”导入{Injectable};
从“@angular/fire/firestore”导入{AngularFirestore}”;
@可注射()
出口级货运服务{
篮子项目:对象[]=[];
构造函数(私有数据库:AngularFirestore){}
addToCart(产品){
//如果产品已经在篮子里
//修理我的篮子应该变异,而不是产品
for(设i=0;i”,product,“但它确实如此”);
返回;
}
}
这个。篮子物品。推(产品);
}
removeFromCart(索引){
本规范。篮子项目。拼接(索引,1);
}
getItems(){
归还这个篮子物品;
}
clearCart(){
this.basketItems=[];
归还这个篮子物品;
}
}
为准确度更新此返回一个参考:
getItems() {
return this.items;
console.log(this.items);
}
你把它分配给你的篮子:
ngOnInit() {
this.basket = this.cartService.getItems();
}
所以它们都指向同一个参考点。当您对购物车服务项目进行更改时,您还可以修改购物篮
如果你想避免这种行为,你可以用这样的东西
getItems() {
return this.items.slice(0); // or [...this.items] a.k.a create a new instance every time
console.log(this.items);
}
供您编辑:
if (product === this.basketItems[i]) { // you check exactly they have same reference
let originalPrice =
this.basketItems[i].price / this.basketItems[i].count;
this.basketItems[i].count = this.basketItems[i].count + 1;
this.basketItems[i].price = this.basketItems[i].price + originalPrice;
console.log("this should not mutate ===>", product, "but it does");
因此,如何修改引用并不重要。它们都会被修改
因此,您正在往返于相同的对象。
您需要做的是:
this.basketItems.push({...product}); // insert new object everytime
// and checking part should be
if (product.id === this.basketItems[i].id) // they are not same object anymore you can not check reference equality.
您编辑了服务中的项目,而期望组件中的产品被编辑?感谢您发布详细问题!你能澄清一下你希望看到什么吗?您可以编辑具有预期结果的问题。是否尝试调试CartService?我已更新了说明。篮子应该发生变化,而不是用户添加到篮子中的产品。我一直将product对象作为引用而不是值传递。我通过使用Object.assign({},product)修复了这个问题