是否可以使路线模型成为计算/跟踪模型 属性?

Is it possible to make a route's model a computed / tracked property?

我正在尝试让路由的模型挂钩 return 一些数组,该数组使用 Ember later 通过轮询机制不断更新。路由文件如下所示:

export default class IndexRoute extends Route {
  recent: [],

  init() {
    ...
    this.getRecent();
  }

  getRecent() {
    // poll data / fetch latest
    this.recent.push(newStuff);
    
    later(this, this.getRecent, 2000);
  }

  model() {
    return this.recent;
  }
}
 

然后在我的控制器中,我想根据路由的 model:

创建一个 @computed / @tracked 属性
export default class IndexController extends Controller {
  // @tracked model; // this also didn't work
  @computed('model.@each') // this doesn't work
  get computedModel() {
    console.log('computedModel'); // prints only once, when the model hook is first run
    return this.model;
  }
}

我认为 的建议会起作用,但它没有 :(

我看到了 但这是针对 Ember 1.13 的,所以不完全是现代解决方案。

同样 this post 也有过时的内容。

我想做的事情可行吗?或者,我正在考虑将数据移动到 Controller 中,而不是对 Controller 变量进行计算 属性 。采纳所有建议!

您当前方法的根本问题是您没有使用 Ember Array 特定功能。当您在 Ember 中创建数组时,通常会发生一些神奇的事情,这些数组会自动将它们创建为 Ember 数组(至少在使用带有 .create 的旧式语法和原型时允许扩展)。您始终可以显式创建一个 Ember 数组:

import { A } from '@ember/array';

export default class ApplicationRoute extends Route{
  recent = A([]);
}

无论如何,当您只使用 this.recent.push(newStuff); 时,此原生数组原型并未以 Ember 的 tracking/observer 系统可以知道新值已被使用的方式进行检测添加到 this.recent 并随后触发重新渲染。这既适用于跟踪属性,也适用于 Octane 之前的传统观察者系统。

相反,当与模板中显示的数组(即需要观察的数组)交互时,您必须使用特殊的Ember.Array特定函数pushObject,如this.recent.pushObject(newStuff)

getRecent() {
  // poll data / fetch latest
  this.recent.pushObject(this.current);
  this.current = this.current + 1;
    
  later(this, this.getRecent, 2000);
}

如果您想完全使用跟踪 属性 样式,可以避免使用 Ember 数组,但您必须通过将数组重新分配给跟踪 属性 来强制重新计算.这是组件中的示例

import Component from '@glimmer/component';
import { tracked} from '@glimmer/tracking';
import { later } from '@ember/runloop';
export default class extends Component {
  @tracked
  trackedArray = [];

  current = 0;
    constructor(){
    super(...arguments);
    this.doPoll();
  }
    
    doPoll() {
    // essentially pushing but via a reassign with the new element
    // you could also `pushObject` here if that feels better
    this.trackedArray = [...this.trackedArray, this.current];
    this.current = this.current + 1;
    
    later(this, this.doPoll, 2000);
  }
}

这里有一个 Ember Twiddle 显示了两种方法的实际应用。

PS。路由的 model 属性 只是准动态的。在过渡期间,model 挂钩的 return 值自动分配给路由的 currentModel 属性。然后这个值作为第二个参数传递到 setupController 并自动分配给控制器的 model 属性 如果没有定义 setupController 或者如果 setupController 调用 super 的基本实现。当为特定路由调用 modelFor 时,currentModel 属性 被 returned 并且 model 不会被重新调用。这就是说,在 model 函数中进行轮询本身不会自动更新控制器的 model 属性。在您的示例中一切正常,因为 model 引用永远不会改变(您只是在改变数组)。