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



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

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

我原以为这篇SO帖子的建议会奏效,但没有:(

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

同样,这篇文章也有过时的内容。

我想做的事情可能吗?或者,我正在考虑将数据移动到Controller中,并生成Controller变量的计算属性。采纳所有建议!

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

import { A } from '@ember/array';
export default class ApplicationRoute extends Route{
recent = A([]);
}

不管怎样,当您只使用this.recent.push(newStuff);时,这个原生阵列原型并没有以Ember的跟踪/观察者系统可以知道this.recent中添加了一个新值并随后触发重新应答的方式进行检测。这既适用于跟踪属性,也适用于传统的观察器系统前辛烷值。

相反,当与模板中显示的数组(即需要观察的数组(交互时,必须使用特殊的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钩子的返回值会自动指定给路由的currentModel属性。然后,如果没有定义setupController或者如果setupController调用基本实现的super,则将该值作为第二参数传递到setupController中,并自动分配给控制器的model属性。当为特定路由调用modelFor时,返回currentModel属性,并且不重新调用model。这就是说,在model函数中进行轮询本身不会自动更新控制器的model属性。在您的示例中,一切都很好,因为model引用从未更改(您只是在更改数组(。

最新更新