英文原文:http://emberjs.com/guides/object-model/computed-properties-and-aggregate-data/

Computed Properties and Aggregate Data

计算属性和带@each的集合数据

Often, you may have a computed property that relies on all of the items in an array to determine its value. For example, you may want to count all of the todo items in a controller to determine how many of them are completed.

计算属性时常依赖一个数组中的全部元素来计算其值。例如,要知道有多少已经完成的待办事项,那么需要计算控制器中所有的待办事项才能得出结果。

Here’s what that computed property might look like:

下面是一个计算属性的示例:

  1. App.TodosController = Ember.Controller.extend({
  2. todos: [
  3. Ember.Object.create({ isDone: false })
  4. ],
  5. remaining: function() {
  6. var todos = this.get('todos');
  7. return todos.filterBy('isDone', false).get('length');
  8. }.property('todos.@each.isDone')
  9. });

Note here that the dependent key (todos.@each.isDone) contains the special key @each. This instructs Ember.js to update bindings and fire observers for this computed property when one of the following four events occurs:

这里需要注意的是依赖(todos.@each.isDone)中包含一个特殊的关键字@each。使用了@each意味着Ember.js在下述的四种情况下,将更新计算属性的绑定和触发其观察器:

  1. The isDone property of any of the objects in the todos array changes.
  2. An item is added to the todos array.
  3. An item is removed from the todos array.
  4. The todos property of the controller is changed to a different array.

  5. todos数组中任意一个元素的isDone属性发生改变;

  6. todos数组中添加了一个新成员;
  7. todos数组中有一个成员被移除了;
  8. 控制器的todos数组变为了另外一个不同的数组。

In the example above, the remaining count is 1:

在上面的示例中,remaining1

  1. App.todosController = App.TodosController.create();
  2. App.todosController.get('remaining');
  3. // 1

If we change the todo’s isDone property, the remaining property is updated automatically:

如果改变待办事项的isDone属性,remaining属性会被自动更新:

  1. var todos = App.todosController.get('todos');
  2. var todo = todos.objectAt(0);
  3. todo.set('isDone', true);
  4. App.todosController.get('remaining');
  5. // 0
  6. todo = Ember.Object.create({ isDone: false });
  7. todos.pushObject(todo);
  8. App.todosController.get('remaining');
  9. // 1

Note that @each only works one level deep. You cannot use nested forms like todos.@each.owner.name or todos.@each.owner.@each.name.

注意@each只工作在第一级。不能嵌套使用,如:todos.@each.owner.name或者todos.@each.owner.@each.name