为什么这不起作用? (SproutCore& Todos示例)

时间:2012-08-20 20:55:00

标签: sproutcore

我正在尝试修改Todos示例以更好地理解框架。

我正在尝试修改todosController以添加一个'completed'计算属性,该属性返回所有已完成的待办事项。最重要的是,我正在尝试更新'areAllCompleted'属性。

我有这段代码,当'completed'发生变化时,它不会更新'areAllCompleted'。

TodosThree.todosController = SC.ArrayController.create({
    completed: function(){
        if(this.get('content')){
            return this.get('content').find(
                SC.Query.local(
                    TodosThree.Todo,
                    'isCompleted = true'
                )
            );
        }
        else {
            return [];
        }
    }.property('content').cacheable(),
    areAllCompleted: function (k, v) {
        console.log('get');
        if (v !== undefined) {
            this.setEach('isCompleted', v);
        }

        return this.getPath('completed.length') === this.get('length');
            # This .property definition doesn't work with .*completed.length .. ?
    }.property('length','.*completed.length')
});

但是,如果我稍微更改代码以添加绑定,则可以正常工作:

TodosThree.todosController = SC.ArrayController.create({
    completed: function(){
        if(this.get('content')){
            return this.get('content').find(
                SC.Query.local(
                    TodosThree.Todo,
                    'isCompleted = true'
                )
            );
        }
        else {
            return [];
        }
    }.property('content').cacheable(),
                                    # For some reason, this binding works ...
    completedLengthBinding: SC.Binding.oneWay('.*completed.length'),
    areAllCompleted: function (k, v) {
        console.log('get');
        if (v !== undefined) {
            this.setEach('isCompleted', v);
        }

        return this.getPath('completed.length') === this.get('length');
            # If I reference the binding that references completed, this now works ...
    }.property('length','completedLength')
});

为什么这种微妙的差异会突然变得有效?

感谢。

1 个答案:

答案 0 :(得分:1)

当您使用.property()方法时,参数应该是对象的直接属性;因此,它不会扩展您传递的属性路径(.*completed.length)。当您设置绑定时,您基本上告诉SproutCore您希望路径(.*completed.length)绑定到对象的属性,这就是第二个工作的原因;因为它已成为一个简单的财产。

由于您是根据完成情况设置这两个方法,因此您可以采用的另一种方法是使用.observes()的单个函数 跟随属性路径,但是有点复杂。以下是我可能会如何处理这个问题:

/*
 * Note that using a store.find will auto-update when new todos are pushed
 * into the store, so there is no need to reset this every time.
 */
completed: TodosThree.store.find(
  SC.Query.local('TodosThree.Todo', 'isCompleted = true')
),


/*
 * Go ahead and grab the length so we can use it as a dependent property below
 */
completedLengthBinding: '*completed.length',


/*
 * Create the property function
 */
allAreCompleted: function(key, value) {
  if (value !== undefined) {
    this.setEach('isCompleted', value);
  }

  return this.everyProperty('isCompleted');
}.property('completed', 'completedLength')

有几点需要注意:由于您想要致电allAreCompleted()并传递一个值,因此 DO 希望将其作为属性,而不仅仅是观察者。从技术上讲,你可以使用一个既作为观察者又作为属性更新程序的函数,但我认为这更清楚。

另外,请注意使用everyProperty()方法,该方法将遍历每个待办事项并确保所有待办事项的传递属性为true。

希望这有帮助!请询问您是否需要澄清:-D