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

vi4fp9gy  于 2022-10-20  发布在  其他
关注(0)|答案(2)|浏览(149)

因此,我的情况如下:我得到了一个组件,它有两个输入字段,表示联系人,并填充了来自服务的数据:

@service('contact-data') contact;

每个字段代表一个属性,可通过

{{contact.properties.foo}}

我将属性保存为JS对象,以便在使用它们时轻松过滤出空字段,我用@tracked跟踪它,如下所示:

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

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

但是,属性无法在组件中正确重新呈现,文本字段也无法更新。
我很感激你能帮我这个忙!谢谢

vohkndzv

vohkndzv1#

每当你有一堆需要跟踪的嵌套状态时,仅仅跟踪顶级对象不会导致对该对象内部的更新传播出去。您需要跟踪内部属性,您需要重置正在跟踪的整个对象。
您基本上有两个粗略的选项来处理这些内部属性的更新:
1.如果对象有一个众所周知的形状,请将其提取到一个在字段上使用@tracked的实用程序类中,并在创建服务时示例化该实用程序类。然后更新这些字段。
1.如果对象真的像哈希Map一样被使用,那么您有两个变体选项:
1.如果不需要IE11支持,请使用https://github.com/pzuraq/tracked-built-ins
1.执行“纯功能更新”,即执行this.properties = { ...this.properties, foo: newValue };之类的操作
其中,(1)几乎总是最便宜、性能最好的。执行(2.1)会稍微贵一些,因为它需要使用Proxy,但还不够您通常会注意到的。执行(2.2)将最终触发应用程序中任何地方使用的properties中的every属性的重新渲染,即使它没有更改。
在您所描述的例子中,字段似乎是众所周知的,这意味着您应该访问该类。解决方案可能如下所示:

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 updateProperty(name, value) {
    this.properties[name] = value;
  }
}

请注意,@trackedinstalls getters and setters in place of plain class properties,因此,如果您需要在某个地方或类似的地方将其用于JSON负载,您还需要在实用程序类上实现toJSON

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

  toJSON() {
    let { id, foo, bar } = this;
    return { id, foo, bar };
  }
}
gj3fmq9x

gj3fmq9x2#

还有另一个add-on,它对数组和对象执行与跟踪内置程序基本相同的操作。
它是一个代理,基本上通知根用户某个地方发生了更新。相对于跟踪内置的优点是嵌套深度不受限制,因为JSON通常具有深度嵌套。
在性能方面,其缺点与跟踪内置程序类似。尽量少用它,并且尽量不要在具有数百行/数千行的表中使用它,因为重新渲染将不会有性能。

相关问题