2

我制作了一个图表组件,我希望它在发生以下任一情况时呈现:

  1. 它的data属性变化
  2. 它被插入到 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可以防止这种情况发生,但我想不会 - 或者我使用不正确。似乎我需要的不仅是检查模型是否已加载,还要检查控制器是否已完成其内容的换出。我将不胜感激任何想法!

4

1 回答 1

0

我最终content在输入索引路由时手动清除了控制器上的属性:

App.IndexRoute = Ember.Route.extend({
  setupController: function(controller, model) {
    this.controllerFor('monthlyReport').set('content', null);
    this.controllerFor('companies').set('content', null);
  }
});
于 2013-09-30T14:25:16.477 回答