首页 > 解决方案 > 是否可以使路线模型成为计算/跟踪的属性?

问题描述

我正在尝试让路由的模型挂钩返回一些数组,该数组通过使用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;
  }
}
 

然后在我的控制器中,我想根据路由创建一个@computed/属性:@trackedmodel

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 的,因此不完全是现代解决方案。

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

我正在尝试做的事情可能吗?或者,我正在考虑将数据移动到控制器中,并改为创建控制器变量的计算属性。采纳所有建议!

标签: ember.jsember-octane

解决方案


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

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

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

无论如何,当您只使用 时this.recent.push(newStuff);,这个原生数组原型并没有以 Ember 的跟踪/观察器系统可以知道已添加新值this.recent并随后触发重新渲染的方式进行检测。这适用于跟踪属性以及传统的观察者系统 pre-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钩子的返回值会自动分配给路由的currentModel属性。然后这个值作为第二个参数传入,如果没有定义或调用基本实现,则setupController自动分配给控制器的model属性。当为特定路由调用时,将返回该属性并且不会重新调用。这就是说,在函数本身中进行轮询不会自动更新控制器的属性。在您的示例中一切正常,因为引用永远不会改变(您只是在改变数组)。setupControllersetupControllersupermodelForcurrentModelmodelmodelmodelmodel


推荐阅读