我正试图让路由的模型挂钩返回一些数组,该数组通过使用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
引用从未更改(您只是在更改数组(。