重新排序用于创建子视图的数组后,Ember视图未更新

时间:2012-03-06 22:11:14

标签: arrays sorting ember.js

我有一个包含一系列活动的活动视图。有时基于用户可以更新的计算属性(distanced_from_home)对该数组进行排序。对数组进行排序时,我希望根据新顺序重新呈现子视图。这是我的模板和视图:

的index.html

  <script type="text/x-handlebars" data-template-name="activities">
    <h1>Activities</h1>
    {{#each activities}}
      {{view App.ActivityView activityBinding="this"}}
    {{/each}}
  </script>

app.js

  App.ActivitiesView = Em.View.extend({
    templateName: 'activities',
    activities: (function() {
      var list;
      list = App.activityController.activities;
      console.log("Activities View");
      console.log(list);
      return list;
    }).property('App.activityController.activities', 'App.activityController.activities.@each.distance_to_home').cacheable()
  });

当我更改distance_to_home属性时,console.log输出显示列表数组已正确排序,但子视图不会以新顺序重新呈现。如果我离开这个视图然后回到它(它再次渲染),那么就会显示正确的顺序。

如何让视图自动更新?

谢谢,

修改

这似乎正在工作here并且我的'活动'计算函数肯定会触发,但没有重新排序视图......我也尝试使用观察者,但结果是相同的。

  App.ActivitiesView = Em.View.extend({
    templateName: 'activities',
    classNames: ['activities rounded shadow'],
    homeBinding: 'App.user.home',
    activities: [],
    homeChanged: (function() {
      console.log("homeChanged()");
      this.set('activities', App.activityController.activities.sort(this.compare_activities));
      return null;
    }).observes('home'),

    compare_activities: function(a, b) {
      var result;
      result = 0;
      if (App.user.home != null) {
        result = a.get('distance_to_home') - b.get('distance_to_home');
      }
      return result;
    },

  });

我还尝试将'activities'参数设置为空数组,然后将其重置为有序数组以强制重新渲染,但这没有任何效果。

  App.ActivitiesView = Em.View.extend({
    templateName: 'activities',
    classNames: ['activities rounded shadow'],
    homeBinding: 'App.user.home',
    activities: [],
    homeChanged: (function() {
      console.log("homeChanged()");
      this.set('activities', []);
      this.set('activities', App.activityController.activities.sort(this.compare_activities));
      return null;
    }).observes('home'),

    compare_activities: function(a, b) {
      var result;
      result = 0;
      if (App.user.home != null) {
        result = a.get('distance_to_home') - b.get('distance_to_home');
      }
      return result;
    },

  });

编辑(第二个)

所以似乎使用Ember.copy最终解决了这个问题。将数组属性设置为空数组(或null)没有任何效果。这是最终有效的View代码:

  App.ActivitiesView = Em.View.extend({
    templateName: 'activities',
    classNames: ['activities rounded shadow'],
    homeBinding: 'App.user.home',
    activities: [],
    homeChanged: (function() {
      var list;
      list = App.activityController.activities.sort(this.compare_activities);
      this.set('activities', Ember.copy(list), true);
      return null;
    }).observes('home'),
    compare_activities: function(a, b) {
      var result;
      result = 0;
      if (App.user.home != null) {
        result = a.get('distance_to_home') - b.get('distance_to_home');
      }
      return result;
    }
  });

2 个答案:

答案 0 :(得分:10)

这有帮助吗? http://jsfiddle.net/rNzcy/

把这个简单的例子放在一起,我有点困惑为什么在ArrayController中对内容数组进行排序时,视图更新没有“正常工作”。看起来有两件简单的事情可以触发视图更新。之一:

  • 将内容数组设置为null,对原始内容进行排序,然后设置已排序的内容。

  • 通过Ember.copy()
  • 对内容数组进行排序时克隆

我猜Ember会检测何时设置了一个全新的Array对象,并触发所有预期的绑定/视图更新。否则,它可能正在进行某种缓存,如果Array对象没有改变(即它已经就地排序),那么没有绑定会触发?只是猜测。

更新: 请参阅讨论@ https://github.com/emberjs/ember.js/issues/575#issuecomment-4397658,它使用propertyWillChange()和propertyDidChange()(http://jsfiddle.net/rNzcy/4/)改进了解决方法 - 应该比克隆大型数组更有效率。 / p>

答案 1 :(得分:3)

我遇到了同样的问题。而且我认为观察array.@eacharray.length是不错的做法。最后我发现了http://jsfiddle.net/rNzcy/4/,即致电this.propertyDidChange('foo')