2

グラフ コンポーネントを作成し、次のいずれかが発生したときにレンダリングするようにします。

  1. そのdata性質が変化する
  2. DOMに挿入されます

問題は、これらのイベントが両方とも発生すると、チャートが 2 回レンダリングされることです。

コンポーネントは次のとおりです。

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 を作成する時間がありませんが、1 つのケースを除いてすべてが期待どおりに機能します:indexルートで開始し、モデルをロードしてからルートに戻る場合indexです。この時点で、前のルート (会社 A、B、および C) のデータが読み込まれますが、indexルート上にいるため、コンポーネントはレンダリングされません。ここで、新しいルート (会社 D、E、F など)をクリックすると、次のようになります (私の知る限り):

  • 約束が解決し、新しい会社がロードされるまで何も起こりません
  • それらが読み込まれるとすぐに、companiesテンプレートがレンダリングされます。didInsertElementこれは私のコンポーネントでトリガーされ、update関数を実行します。
  • myのdata計算されたプロパティがCompaniesController再度計算され、その change イベントが発生します。
  • 私のコンポーネントのupdateメソッドは、変更を監視し、dataそれ自体を再レンダリングします。

そのため、チャートは 2 回レンダリングされます。1 回は古いデータで、もう 1 回は新しいデータでレンダリングされます。瞬間的であれば問題ないかもしれませんが、滑らかなアニメーションなので目立ちます。

を使用Ember.run.onceするとこれを防ぐことができると思いましたが、そうではないと思います-または、間違って使用しています。モデルがロードされているかどうかだけでなく、コントローラーがコンテンツのスワップアウトを完了したかどうかを確認する必要があるようです。どんなアイデアでも大歓迎です!

4

1 に答える 1