【问题标题】:The value of object's property is not being changed in the Local Storage in Ember在 Ember 的本地存储中,对象属性的值没有被更改
【发布时间】:2020-05-20 04:19:46
【问题描述】:

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

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    基于@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

    【讨论】:

      【解决方案2】:

      您需要使 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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-18
        • 1970-01-01
        • 2017-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-18
        相关资源
        最近更新 更多