Ember的“本地存储”中未更改对象属性的值

时间:2020-02-04 10:46:11

标签: javascript ember.js

我正在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的值未在本地存储中更新。

2 个答案:

答案 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