<Page>
  <h1>使用数据集合</h1>
  <h2>创建数据集合</h2>
  <p>数据集合的概念和单个数据的概念非常类似。
    我们以创建一个 Todo 列表为例。首先要使用 Roof 提供的 Nodes 对象来创建集合类。</p>

  <Code type='javascript'>{`
var Todos = Nodes.createClass()
  `}</Code>

  <p>然后使用这个类来实例化对象。</p>

  <Code type='javascript'>{`
//可以传入初始数据
var todos = new Todos([{
    content : "write roof book",
    owner : "jhon"
    },{
    content : "run test of roof",
    owner : "saber"
}])
  `}</Code>

  <h2>操作数据集合</h2>

  <h3>类数组操作</h3>

  <p>数据集合本身已经包含了很多常见的类数组操作函数，我们接着上面的代码继续举例</p>

  <Code type='javascript'>{`
    //插入新数据，默认插到尾部
    todos.insert({content:"swim",owner:"jhon"})
    //通过第二个参数指定插入位置
    todos.insert({content:"swim",owner:"jhon"}, 0)

    //更新数据,这个接口接受两个参数
    //where  : 匹配的数据
    //setObj : 新的数据
    //例如，我们让jhon的所有任务都变成basketball
    todos.update({owner:"jhon"},{content:"basketbal"})

    //删除数据
    todos.remove({owner:"jhon"})

    //清空集合
    todos.empty()

    //批量插入
    todos.fill([{owner:"jhon"},{owner:"maya"}])

    //批量替换
    todos.empty().fill([{owner:"jhon"},{owner:"maya"}])

    //查找某些数据。
    //注意，使用这个方法或得到一个新集合
    //但其中的单条数据，只是之前数据的引用。
    todos.filter( function(todo) ){
    return todo.get("owner") === "jhon"
  })

    //查找单个数据
    todos.findOne({owner:"jhon"})

    //查找某个数据的位置，只返回第一个找到的数据位置
    todos.indexOf({owner:"jhon"})

    //遍历
    todos.forEach(function(todo){
    console.log(todo.get("owner"))
  })

    //变成纯数据数组
    todos.toArray()
    `}</Code>

  <h3>与服务器端通信操作</h3>

  <p>如果服务器端提供数据批量操作的接口，那么我们可以非常轻松地通过集合的 push 和 pull 方法与服务器端通信。这同样需要开发者自己编写 middleware 实现。在 middleware 中 我们可以轻松地拿到集合l里进行了修改的数据：</p>

  <Code type='javascript'>{`
  var nodesToUpdate = this.find(function(node){
    return node.is("dirty")
}).toArray()
  `}</Code>

  <h3>集合事件的监听</h3>

  <p>数据集合和单个数据一样，当执行 insert 等方法时，它会抛出休息来供我们监听。例如
</p>

  <Code type='javascript'>{`
todos.on("inserted", function(){
    console.log("新插入数据")
})

todos.insert({content:"just for fun",owner:"jhon"})
  `}</Code>

  <h3>单个数据的销毁</h3>

  <p>我们通过 `find`, `findOne` 等函数获取到集合中的单个数据后，可以调用数据的 `destroy` 方法。当单个数据被销毁时，集合会自动移除该数据。</p>

  <h3>自定义API</h3>

  <p>对集合也可以自定义API：</p>

  <Code type='javascript'>{`
  var UserList = Nodes.createClass({
        setAllName : function(name){
          return this.forEach(function(node){
            node.set("name", name)
          })
        },
        getTotalAge : function( ){
          var total = 0
          this.forEach(function( node){
            total += node.get("age")
          })
          return total
        }
      })

var users = new UserList
users.insert({"name":"jhon", age:21})
users.insert({"name":"maya", age:32})

//可以使用api了
console.log( users.getTotalAge() ) //53

users.setAllName("jesper")
console.log(users.get(0).get("name")) // "jesper"
console.log(users.get(1).get("name")) // "jesper"
  `}</Code>

  <h2>指定集合中的单个数据的类型</h2>

  <p>可以在创建集合时，指定单个数据的类型。</p>

  <Code type='javascript'>{`
  var Todo = Node.createClass()
var Todos = Nodes.createClass({
    $factory : Todo
})
  `}</Code>

  <p>如果你的集合没有使用自定义 api， 那么还可以简写:</p>

  <Code type='javascript'>{`
  var Todo = Node.createClass()
var Todos = Nodes.createClass( Todo )
  `}</Code>

  <p>注意，即使你没有为单个元素指定 class，其中的每个元素也会被匿名的 Node class包裹。所以你通过 find 等 api 获取到的单个元素，仍然有 get\set 等Node api。</p>

  </Page>




