我正在Ember建立一家商店,其中包含当用户点击“
添加到购物车按钮。每个产品都是具有名为ordered_quantity
的属性的对象,当用户尝试从购物车中删除产品时,我正在尝试更改此属性的值。 (例如:ordered quantity: 8
,单击按钮时应为7
)。
我的服务文件中包含以下代码:
remove(item) {
let new_arr = this.get('items');
let elementIndex = new_arr.findIndex(obj => {
return obj.id === item.id;
});
if (elementIndex !== -1) {
new_arr[elementIndex].ordered_quantity = new_arr[elementIndex].ordered_quantity - 1;
}
this.set('cart.items', new_arr);
}
我正在使用本地存储附件(https://github.com/funkensturm/ember-local-storage#methods)
我将执行以下操作:
actions: {
removeFromCart(){
this.get('cart').remove(this.product);
}
}
当我尝试运行以下代码时,出现错误:
未捕获的错误:断言失败:您试图将[object Object] .ordered_quantity更新为“ 7”,但是正在由跟踪上下文(例如模板,计算属性或观察者)进行跟踪。为了确保上下文正确更新,必须在更新属性时使该属性无效。您可以将属性标记为
@tracked
,或使用@ember/object#set
来完成此操作。
我尝试使用set函数,如下所示:
let updated = item.ordered_quantity - 1;
set(item, 'ordered_quantity', updated);
https://api.emberjs.com/ember/release/functions/@ember%2Fobject/set,并且代码按预期运行,没有错误,但是我的属性ordered_quantity
的值未在本地存储中更新。
答案 0 :(得分:4)
您需要使set
函数适应您的用例:
remove(item) {
let new_arr = this.get('items');
let elementIndex = new_arr.findIndex(obj => {
return obj.id === item.id;
});
if (elementIndex !== -1) {
set(new_arr[elementIndex], 'ordered_quantity', new_arr[elementIndex].ordered_quantity - 1);
}
this.set('cart.items', new_arr);
}
答案 1 :(得分:0)
基于@Lux的原始答案(并在Ember 3.16+时代进行更新),我想补充一点,您可以使用函数式编程模式来进行一些清理:
如果在您的cart
服务中,项目为@tracked
,如下所示:
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
export default class CartService extends Service {
@tracked items = [];
}
注意:假设未跟踪ordered_quantity
。
remove(item) {
for (let obj of this.items) {
if (item.id !== obj.id) continue;
// set must be used because quantity is not known to the tracking system
set(obj, 'ordered_quantity', obj.ordered_quantity - 1);
});
// invalidate the reference on the card service so that all things that
// reference cart.items re-compute
this.cart.items = this.items;
}
这是现场演示:https://ember-twiddle.com/e18433b851091b527512e27ae792640c?openFiles=components.demo%5C.js%2C
还有一个实用程序插件,它允许与数组,对象等进行更符合人体工程学的交互:https://github.com/pzuraq/tracked-built-ins
上面的代码将如下所示:
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { TrackedArray } from 'tracked-built-ins';
export default class CartService extends Service {
@tracked items = new TrackedArray([]);
}
,然后在您的组件中:
remove(item) {
for (let obj of this.items) {
if (item.id !== obj.id) continue;
// set must be used because quantity is not known to the tracking system
set(obj, 'ordered_quantity', obj.ordered_quantity - 1);
});
}
这是现场演示:https://ember-twiddle.com/23c5a7efdb605d7b5fa9cd9da61c1294?openFiles=services.cart%5C.js%2C
然后您可以将其更进一步,并在“项目”中添加跟踪。
因此您的remove方法将如下所示:
remove(item) {
for (let obj of this.items) {
if (item.id !== obj.id) continue;
obj.ordered_quantity = obj.ordered_quantity - 1;
});
}
这是一个实时演示:https://ember-twiddle.com/48c26e2e0f0e5f3ac7685e4bdc0eda4e?openFiles=components.demo%5C.js%2C