我制作了一个图表组件,我希望它在发生以下任一情况时呈现:
- 它的
data
属性变化 - 它被插入到 DOM
问题是,如果这两个事件都发生,图表会被渲染两次。
这是组件:
App.BarChartComponent = Ember.Component.extend({
classNames: ['chart'],
chart: BarChart().margin({left: 40, top: 40, bottom: 80, right: 40}),
didInsertElement: function() {
Ember.run.once(this, 'update');
},
update: function() {
if (this.get('isLoaded')) {
d3.select(this.$()[0])
.data([ this.get('data') ])
.call(this.get('chart'));
}
}.observes('data')
});
我正在这样使用它(它在公司模板中呈现)
{{bar-chart data=controller.controllers.companies.data
isLoaded=controller.controllers.companies.model.isLoaded}}
控制器看起来像这样(更改路由会更新CompaniesController
模型):
App.CompaniesController = Ember.ArrayController.extend({
data: function() {
if (!this.get('model.isLoaded')) {return;}
var data = this.map(function(company) {
return {
category: company.get('name'),
count: company.get('newContracts'),
};
});
return data;
}.property('model')
});
我现在没有时间制作 jsfiddle,但除了一种情况外,一切都按预期工作:我从index
路线开始,然后加载模型,然后返回index
路线。此时,为先前的路线(例如公司 A、B 和 C)加载了数据,但是因为我在index
路线上,所以组件没有被渲染。现在,如果我点击一条新路线(比如公司 D、E、F),会发生以下情况(据我所知):
- 在承诺解决并且新公司加载之前什么都不会发生
- 一旦它们被加载,
companies
模板就会被渲染。这会在我的组件中触发didInsertElement
,并运行该update
功能。 data
再次计算 my中的计算属性CompaniesController
,触发其更改事件。- 我的组件中的
update
方法会观察自己的变化data
并重新渲染。
因此,图表会被渲染两次,一次使用旧数据,一次使用新数据。如果它是瞬时的,也许没关系,但因为它有一个流畅的动画,所以很明显。
我认为 usingEmber.run.once
可以防止这种情况发生,但我想不会 - 或者我使用不正确。似乎我需要的不仅是检查模型是否已加载,还要检查控制器是否已完成其内容的换出。我将不胜感激任何想法!