【问题标题】:How to pass a @tracked object from an Ember route model hook如何从 Ember 路由模型钩子传递 @tracked 对象
【发布时间】:2020-08-03 07:34:24
【问题描述】:

我的问题有两个:

  1. 在哪里放置某种轮询逻辑的最佳位置 - 在路由文件中,对吗?

  2. 如何将这个不断更新的值从 Route 传递给某个子组件?将某个变量标记为“@tracked”,然后通过model 挂钩传递跟踪变量?

假设我有这样的事情:

routes/index.js

export default class IndexRoute extends Route {
  @tracked
  recent: {
    A: 0,
    ...
  },

  constructor() {
    super(...arguments);
    this.getRecent();
  }

  getRecent() {
    // poll data / fetch latest
    const {A, ...partialObject} = this.recent;
    
    this.recent = { ...partialObject, A: <some new value fetched>};;
    
    later(this, this.getRecent, 2000);
  }

  model() {
    return this.recent;
  }
}

application.hbs

<p>constantly updating "this.recent": {{ this.model.A }} </p>

我想如果我像这样使用模型挂钩,它将被跟踪并因此自动更新,但事实并非如此。我有这个样本Ember Twiddle 模拟了我正在尝试做的事情。我试图通过重新分配整个变量来强制重新计算,但它不起作用。

这个问题是我的initial question here 的深入探讨。

【问题讨论】:

    标签: ember.js ember-octane


    【解决方案1】:

    您正在返回对存储在模型挂钩中this.recent 中的对象的引用。但是getRecent 方法不会更改该对象,而是覆盖this.recent。在第一次执行getRecent 方法后,路由模型和this.recent 不再是同一个对象。通过this.modelFor(this.routeName)访问的路由模型为初始值,this.recent为新值。

    您想改变从模型挂钩返回的对象。

    您的示例中给出的对象具有固定的架构。这允许您将属性 A 标记为已跟踪:

      recent: {
        @tracked A: 0,
        ...
      }
    

    目前您在模型挂钩中返回 this.recent 的值。但不是在getRecent 方法中覆盖它,而是只更改它的属性A 的值:

      getRecent() {  
        this.recent.A = <some new value fetched>;
        
        later(this, this.getRecent, 2000);
      }
    

    如果您不知道模型挂钩中返回的对象的架构,或者您正在处理一个数组,那么它会稍微复杂一些。你不会有一个属性可以用@tracked 来装饰。在这种情况下,我建议使用 tracked-built-ins 包。

    对于数组,您还可以从 @ember/array/mutable 包回退到旧版 MutableArray。但在这种情况下,您必须确保使用它的自定义方法来操作数组(例如 pushObject 而不是 push)。

    【讨论】:

    • 哦,我认为this.recent = { ...partialObject, A: &lt;some new value fetched&gt;}; 会覆盖所有this.recent - 不是这样吗? :o
    • re:“您正在返回对存储在模型挂钩中 this.recent 中的对象的引用。” - 有没有办法返回实际对象呢?还是我不应该这样做,而是将@tracked 添加到您提到的对象中的每个键中?
    • 您正在返回一个对象。但是当您更改this.recent 时,返回的对象不受影响。也许这段代码说明了这一点:Ember 框架调用this.model()。之后this.recent === this.modelFor(this.routeName) 是真的。现在this.getRecent() 运行,它改变了this.recentthis.recent === this.modelFor(this.routeName) 是假的。路线模型挂钩不会自动跟踪。当其中消耗的值发生变化时,它不会重新运行。您不应该替换其中返回的对象,而是对其进行操作。
    • 啊,所以基本上创建了对象的副本并将其传递给值this.modelFor(this.routeName),稍后当getRecent 运行时,它会更改未跟踪的原始对象的值,因为@ 987654353@ 钩子未被跟踪(而像get 这样的东西会?我还没有让它工作,也许我不应该在路由中有@tracked 对象?)
    • 您的问题有所不同。 Ember Octane 中的大多数派生状态都是自动跟踪的。如果在 getter 中消耗的跟踪值发生更改,则再次执行该 getter。类似于模板助手或修饰符在其中一个参数发生变化时再次运行的方式。但是model 钩子是不同的。它不是自动跟踪的。这意味着如果跟踪值发生变化,它不会再次运行。它只在转换的情况下运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多