简体   繁体   English

如何在 Ember Octane 中更新嵌套状态

[英]How to update nested state in Ember Octane

So my situation is as follows: I got a component with a couple of input fields that represent a contact and are filled with data from a service:所以我的情况如下:我得到了一个包含几个输入字段的组件,这些输入字段代表一个联系人并填充了来自服务的数据:

  @service('contact-data') contact;

Each field stands for one property that is accessed via每个字段代表一个通过访问的属性

{{contact.properties.foo}}

I have the properties saved as a JS object to easily filter out empty fields when using them and I tracked it with @tracked like so:我将属性保存为 JS 对象,以便在使用它们时轻松过滤掉空字段,并使用@tracked跟踪它, @tracked所示:

export default class MyService extends Service {
  @tracked properties = {id: 0, foo: "", bar : "abc", };

  @action updateProperty(name, value) {
    this.properties[name] = value;
  }
}

However, the properties do not re-render properly in the component and the textfields do not get updated.但是,属性不会在组件中正确重新呈现,并且文本字段不会更新。

I'd appreciate any help with this!我将不胜感激! Thanks!谢谢!

Any time you have a bunch of nested state like that which needs to be tracked, just tracking the top-level object won't cause updates to the internals of that object to propagate out.任何时候你有一堆需要跟踪的嵌套状态,只跟踪顶级对象不会导致对该对象内部的更新传播出去。 You need to track the internal properties, or you need to reset the whole object you're tracking.您需要跟踪内部属性,或者您需要重置您正在跟踪的整个对象。

You have basically two rough options for dealing with updates to those internal properties:您基本上有两个粗略的选项来处理这些内部属性的更新:

  1. If the object has a well-known shape, extract it into a utility class which uses @tracked on the fields, and instantiate the utility class when you create the service.如果对象具有众所周知的形状,请将其提取到在字段上使用@tracked的实用程序类中,并在创建服务时实例化该实用程序类。 Then updates to those fields will update.然后对这些字段的更新将更新。
  2. If the object is really being used like a hash map, then you have two variant options:如果对象真的像哈希映射一样使用,那么您有两个变体选项:
    1. Use https://github.com/pzuraq/tracked-built-ins , if you don't need IE11 support如果不需要 IE11 支持,请使用https://github.com/pzuraq/tracked-built-ins
    2. Do a "pure functional update", where you do something like this.properties = { ...this.properties, foo: newValue };做一个“纯功能更新”,在那里你做这样的事情this.properties = { ...this.properties, foo: newValue };

Of these, (1) is pretty much always going to be the cheapest and have the best performance.其中,(1) 几乎总是最便宜且性能最好的。 Doing (2.1) will be a little more expensive, because it requires the use of a Proxy , but not enough that you would normally notice.做 (2.1) 会有点贵,因为它需要使用Proxy ,但还不够,你通常会注意到。 Doing (2.2) will end up triggering a re-render for every property in the properties used anywhere in the app, even if it didn't change.这样做(2.2)将最终触发重新绘制在每个属性properties在该应用的任何使用,即使它并没有改变。

In the case you've described, it appears the fields are well known, which means you should reach for that class.在您所描述的情况下,这些字段似乎是众所周知的,这意味着您应该访问该类。 The solution might look something like this:解决方案可能如下所示:

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

class TheProperties {
  @tracked id;
  @tracked foo;
  @tracked bar;
}

export default class MyService extends Service {
  properties = new TheProperties();

  @action updateFoo(newValue) {
    this.properties.foo = newValue;
  }

  @action updateBar(newValue) {
    this.properties.bar = newValue;
  }
}

Note that @tracked installs getters and setters in place of plain class properties , so if you need to use this for a JSON payload somewhere or similar, you'll also want to implement toJSON on the utility class:请注意, @tracked 安装 getter 和 setter 代替普通类属性,因此如果您需要将其用于某处或类似地方的 JSON 有效负载,您还需要在实用程序类上实现toJSON

class TheProperties {
  @tracked id;
  @tracked foo;
  @tracked bar;
  
  toJSON() {
    let { id, foo, bar } = this;
    return { id, foo, bar };
  }
}

There's another add-on that does basically the same thing for Array and Objects as tracked-built-ins.还有另一个附加组件对数组和对象的作用与跟踪内置函数基本相同。

It's a proxy that basically notifies the root that an update has occurred somewhere.它是一个代理,基本上通知根某处发生了更新。 The advantage against tracked-built-ins is that the nesting depth is not limited as it's common for JSON to have deep nesting.与跟踪内置函数相比的优势在于,嵌套深度不受限制,因为 JSON 具有深度嵌套是很常见的。

The drawbacks are similar to tracked-built-ins in terms of performance.在性能方面,缺点类似于内置跟踪。 Use it sparingly and try not to use it in tables with hundreds/thousands of rows as re-rendering is going to be not performant.谨慎使用它并尽量不要在具有数百/数千行的表中使用它,因为重新渲染将没有性能。

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

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