简体   繁体   English

对象属性的值在 Ember 的本地存储中没有改变

[英]The value of object's property is not being changed in the Local Storage in Ember

I'm building a shop in Ember with the list of products that are being added to Local Storage when the user clicks on the add to cart button.我正在 Ember 中建立一个商店,其中包含当用户单击添加到购物车按钮时添加到本地存储的产品列表。 Each product is an object that has a property called ordered_quantity , I'm trying to change this property's value when the user tries to remove the product from the cart.每个产品都是一个对象,它有一个名为ordered_quantity的属性,当用户尝试从购物车中删除产品时,我试图更改此属性的值。 (example: ordered quantity: 8 , when the button is clicked it should be 7 ). (例如: ordered quantity: 8 ,单击按钮时应为7 )。

I have the following code in my service file:我的服务文件中有以下代码:

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);
}

I'm using Local Storage add-on ( https://github.com/funkensturm/ember-local-storage#methods )我正在使用本地存储插件( https://github.com/funkensturm/ember-local-storage#methods

and I have the following action:我有以下行动:

actions: {
  removeFromCart(){
    this.get('cart').remove(this.product);
  }
}

When I try to run the following code I get an error:当我尝试运行以下代码时,出现错误:

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.未捕获的错误:断言失败:您试图将 [object Object].ordered_quantity 更新为“7”,但它正在被跟踪上下文跟踪,例如模板、计算属性或观察者。 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.您可以将该属性标记为@tracked ,或使用@ember/object#set来执行此操作。

I tried using the set function like this:我尝试使用这样的 set 函数:

let updated = item.ordered_quantity - 1;
set(item, 'ordered_quantity', updated);

https://api.emberjs.com/ember/release/functions/@ember%2Fobject/set and the code worked with no errors as expected, but the value of my property ordered_quantity was not updated in the Local Storage. https://api.emberjs.com/ember/release/functions/@ember%2Fobject/set并且代码按预期运行没有错误,但我的属性ordered_quantity的值未在本地存储中更新。

You need to adapt the set function to your use-case:您需要根据您的用例调整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);
}

Based of @Lux's original answer (and to also update for the Ember 3.16+ era), I wanted to add that you could use functional programming patterns to clean things up a little bit:基于@Lux 的原始答案(以及针对 Ember 3.16+ 时代的更新),我想补充一点,您可以使用函数式编程模式来稍微清理一下:

If in your cart Service, items is @tracked , like so:如果在您的cart Service 中,items 是@tracked ,如下所示:

import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';

export default class CartService extends Service {
  @tracked items = [];
}

Note: assumes that ordered_quantity is not tracked.注意:假设没有跟踪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;
}

Here is a live demo: https://ember-twiddle.com/e18433b851091b527512e27ae792640c?openFiles=components.demo%5C.js%2C这是一个现场演示: https : //ember-twiddle.com/e18433b851091b527512e27ae792640c?openFiles=components.demo%5C.js%2C

There is also a utility addon, which allows for more ergonomic interaction with arrays, objects, etc: https://github.com/pzuraq/tracked-built-ins还有一个实用程序插件,它允许与数组、对象等进行更符合人体工程学的交互: https : //github.com/pzuraq/tracked-built-ins

the above code would then look like this:上面的代码看起来像这样:

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([]);
}

and then in your component:然后在您的组件中:

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);
  });
}

Here is a live demo: https://ember-twiddle.com/23c5a7efdb605d7b5fa9cd9da61c1294?openFiles=services.cart%5C.js%2C这是一个现场演示: https : //ember-twiddle.com/23c5a7efdb605d7b5fa9cd9da61c1294?openFiles=services.cart%5C.js%2C

You could then take it a step further, and add tracking to your "items".然后,您可以更进一步,并为您的“项目”添加跟踪。

so then your remove method would look like this:那么您的 remove 方法将如下所示:

remove(item) {
  for (let obj of this.items) {
    if (item.id !== obj.id) continue;

    obj.ordered_quantity = obj.ordered_quantity - 1;
  });
}

And here is a live demo: https://ember-twiddle.com/48c26e2e0f0e5f3ac7685e4bdc0eda4e?openFiles=components.demo%5C.js%2C这是一个现场演示: https : //ember-twiddle.com/48c26e2e0f0e5f3ac7685e4bdc0eda4e?openFiles=components.demo%5C.js%2C

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM