如何根据列表中项目的属性在knockout中计算2个列表?

时间:2016-07-26 05:09:53

标签: knockout.js computed-observable

作为一项学习练习,我有一个待办事项清单。在我看来,我想显示按完成分组的项目。下面是我的viewmodel。我将如何实现我想要实现的目标,如何设置计算的observable?

         function TodoList(name, items) {
        this.name = ko.observable(name === "undefined"? "": name);
        this.todoItems = ko.observableArray(typeof (items) !== "undefined" ? items : []); 
    }

    function TodoItem(name,completed) {
        this.name = ko.observable(name === "undefined" ? "" : name);
        this.completed = ko.observable(completed === "undefined" ? false : completed);
    }

    function TodoListViewModel() {
        var self = this;
        self.todoLists = ko.observableArray([

            new TodoList("Groceries", [
                new TodoItem("Milk", true),
                new TodoItem("Bread",false),
                new TodoItem("Tissues",false)
            ]),
            new TodoList("Luggage", [
                new TodoItem("Hairdryer", false),
                new TodoItem("Toothbrush",false)
            ]),             
        ]);
    }

2 个答案:

答案 0 :(得分:1)

  1. TodoList视图模型中创建计算属性。由于计算机的方法没有任何副作用,因此最好使用ko.pureComputed

    this.completedItems = ko.pureComputed(function() { /* ... */ }, this);
    
  2. 注意:第二个this参数将当前this上下文设置为计算的“所有者”。即:在计算的方法中,this指的是TodoList实例。

    1. 在computed的方法中,评估todoItems可观察数组以创建对其值的预订:

      var currentItems = this.todoItems();
      
    2. completed过滤项目并返回数组:

      return currentItems.filter(function(item) {
        return item.completed();
      });
      
    3. 现在,每个TodoList都有一个已完成项目的计算数组。您可以以类似的方式创建未完成项目的列表。

      如果您想更进一步,并在列表之间对已完成的项目进行分组,您也可以向ko.pureComputed添加TodoListViewModel

      this.allCompletedItems = ko.pureComputed(function() {
        return this.todoLists()
          .map(function(todoList) { return todoList.completedItems(); })
          .reduce(function(result, itemList) { return result.concat(itemList); }, []);
      }, this);
      

      所有代码在一起:

      function TodoList(name, items) {
        this.name = ko.observable(name === "undefined" ? "" : name);
        this.todoItems = ko.observableArray(typeof(items) !== "undefined" ? items : []);
      
        this.completedItems = ko.pureComputed(function() {
          return this.todoItems()
            .filter(function(item) {
              return item.completed();
            });
        }, this);
      }
      
      function TodoItem(name, completed) {
        this.name = ko.observable(name === "undefined" ? "" : name);
        this.completed = ko.observable(completed === "undefined" ? false : completed);
      }
      
      function TodoListViewModel() {
        this.todoLists = ko.observableArray([
          new TodoList("Groceries", [
            new TodoItem("Milk", true),
            new TodoItem("Bread", false),
            new TodoItem("Tissues", false)
          ]),
          new TodoList("Luggage", [
            new TodoItem("Hairdryer", false),
            new TodoItem("Toothbrush", false)
          ]),
        ]);
      
        this.allCompletedItems = ko.pureComputed(function() {
          return this.todoLists()
            .map(function(todoList) {
              return todoList.completedItems();
            })
            .reduce(function(result, itemList) {
              return result.concat(itemList);
            }, []);
        }, this);
      }
      

答案 1 :(得分:0)

您需要定义计算的observable:

    self.completedItems = ko.computed(function() {
      return self.todoLists().reduce(function(result, list) {
         return result.concat(list.todoItems().filter(function(i) { return i.completed(); }));
      }, []);
    });



         function TodoList(name, items) {
        this.name = ko.observable(name === "undefined"? "": name);
        this.todoItems = ko.observableArray(typeof (items) !== "undefined" ? items : []); 
    }

    function TodoItem(name,completed) {
        this.name = ko.observable(name === "undefined" ? "" : name);
        this.completed = ko.observable(completed === "undefined" ? false : completed);
    }

    function TodoListViewModel() {
        var self = this;
        self.todoLists = ko.observableArray([

            new TodoList("Groceries", [
                new TodoItem("Milk", true),
                new TodoItem("Bread",false),
                new TodoItem("Tissues",false)
            ]),
            new TodoList("Luggage", [
                new TodoItem("Hairdryer", true),
                new TodoItem("Toothbrush",false)
            ]),             
        ]);
          
        self.completedItems = ko.computed(function() {
          return self.todoLists().reduce(function(result, list) {
             return result.concat(list.todoItems().filter(function(i) { return i.completed(); }));
          }, []);
        });
    }
    
    ko.applyBindings(new TodoListViewModel());

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<!-- ko foreach: completedItems -->
<div data-bind="text: name"></div>
<!-- /ko -->
&#13;
&#13;
&#13;