对象 属性 的值未在 Ember 的本地存储中更改
The value of object's property is not being changed in the Local Storage in Ember
我正在 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);
}
}
当我尝试 运行 以下代码时出现错误:
Uncaught Error: Assertion Failed: You attempted to update [object Object].ordered_quantity to "7", but it is being tracked by a tracking context, such as a template, computed property, or observer. In order to make sure the context updates properly, you must invalidate the property when updating it. You can mark the property as @tracked
, or use @ember/object#set
to do this.
我试过像这样使用设置函数:
let updated = item.ordered_quantity - 1;
set(item, 'ordered_quantity', updated);
https://api.emberjs.com/ember/release/functions/@ember%2Fobject/set 并且代码按预期工作没有错误,但是我的 属性 ordered_quantity
的值没有在本地存储中更新。
您需要根据您的用例调整 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);
}
基于@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(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
我正在 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);
}
}
当我尝试 运行 以下代码时出现错误:
Uncaught Error: Assertion Failed: You attempted to update [object Object].ordered_quantity to "7", but it is being tracked by a tracking context, such as a template, computed property, or observer. In order to make sure the context updates properly, you must invalidate the property when updating it. You can mark the property as
@tracked
, or use@ember/object#set
to do this.
我试过像这样使用设置函数:
let updated = item.ordered_quantity - 1;
set(item, 'ordered_quantity', updated);
https://api.emberjs.com/ember/release/functions/@ember%2Fobject/set 并且代码按预期工作没有错误,但是我的 属性 ordered_quantity
的值没有在本地存储中更新。
您需要根据您的用例调整 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);
}
基于@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(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