实例教程——代办事项
首先,我们来看一下将要实作的示例。 运行示例
上面例子的代码如下:
<!DOCTYPE html><html><head><link rel="stylesheet" type="text/css" href="/resources/cola-ui/semantic.css"><link rel="stylesheet" type="text/css" href="/resources/cola-ui/cola.css"><script src="/resources/jquery-2.1.3.js"></script><script src="/resources/cola-ui/3rd.js"></script><script src="/resources/cola-ui/semantic.js"></script><script src="/resources/cola-ui/cola.js"></script><script type="text/javascript">cola(function (model) {model.set({todos: [{ title: "Meeting", done: true },{ title: "Date" },{ title: "Lunch" , done: true},{ title: "Play basketball" },{ title: "Game" }],sortOptions: ["", "done", "-done", "title", "-title", "done,title"]});model.action({add: function () {model.get("todos").insert({title: model.get("newItem")});model.set("newItem", null);},delete: function (todo) {todo.remove();},stat: function () {var todos = model.get("todos"), done = 0;todos.each(function (todo) {if (todo.get("done")) done++;});return done + "/" + todos.entityCount;}});});</script></head><body style="padding:20px"><p><input c-bind="newItem"><button c-onclick="add()" c-disabled="newItem?false:true">Add</button></p><p>Filter: <input c-bind="filterParam">Sort: <select c-bind="sortParam" c-options="sortOptions"></select></p><ul><li c-repeat="todo in sort(filter(todos,filterParam),sortParam)"><input type="checkbox" c-bind="todo.done"><span c-bind="todo.title"></span><button c-onclick="delete(todo)">Delete</button></li></ul><p><span c-bind="stat()"></span></p></body></html>
这是一个待办事项的列表界面。虽然界面略显粗糙,但功能已相当完整。
本页面最核心的部分是待办事项的列表,这个列表在HTML中是这样定义的:
<li c-repeat="todo in sort(filter(todos,filterParam),sortParam)"><input type="checkbox" c-bind="todo.done"><span c-bind="todo.title"></span><button c-onclick="delete(todo)">Delete</button></li>
c-repeat指令的第一段todo in sort(filter(todos,filterParam),sortParam)里包含了对两个内置Action的调用,
用于完成对代办事项列表的过滤和排序。其中的filterParam和sortParam并不是两个固定的值,而是两个用于引用Model中数据的数据路径。
一开始我们并没有给Model中的filterParam和sortParam这两个数据项赋值,根据filter和sort这样两种转换器的定义,不传递参数就不会产生效果。
因此,我们一开始看到的列表是所有待办事项的初始顺序。
在列表上方的HTML中,我们可以找到这样一段定义:
<p>Filter: <input c-bind="filterParam">Sort: <select c-bind="sortParam" c-options="sortOptions"></select></p>
这里有一个<input>和一个<select>分别绑定到了之前提到的filterParam和sortParam这两个数据项。其中<select>的备选项的信息由来自于另一个名为sortOptions的数据项,
通过c-options指令完成绑定。
以绑定到filterParam的<input>为例,当用户通过<input>改变了filterParam数据项的值时,由于列表中c-repeat="todo in sort(filter(todos,filterParam),sortParam)"的声明是涉及filterParam数据项的,
因此Cola会重新计算执行c-repeat指令,刷新列表。此时由于filter的条件已发生改变,因此c-repeat重新计算的结果将是跟filterParam过滤后的结果。
这一数据变化最终会自动反应到代办事项的列表中。因此,我们在界面中看到的效果就是,当我们在Filter:后的输入框中输入内容时,下面的代办事项的列表会自动根据我们的录入内容进行数据过滤。
上面<select>的工作原理大致同样如此,这里不做累述。
我们再回到待办事项的列表的模板定义中,其中的<checkbox>的定义并不难理解,需要注意的是最后那个<button>的的定义方式。
为了用这个按钮实现删除当前行的功能,我这样定义了它的事件c-onclick="delete(todo)"。其中的todo是c-repeat产生的迭代变量,代表每一个当前的待办项。
delete()是我们为Model定义的一个Action,它的具体定义是这样的:
model.action({...delete: function (todo) {todo.remove();}...});
即直接删除传入的待办事项。
当一个待办事项被删除后,c-repeat="todo in sort(filter(todos,filterParam),sortParam)"会自动感知到数据的变化,并重新执行迭代,刷新列表。因此该待办事项对应的DOM元素也会自动被移除。
列表下方的统计是这样的定义的:
<p><span c-bind="stat()"></span></p>
其代码主体在Action中。逻辑并不复杂,对todos列表进行一次迭代,统计出已完成的代办事项数并返回。
model.action({...stat: function () {var todos = model.get("todos"), done = 0, total = 0;todos.each(function (todo) {if (todo.get("done")) done++;});return done + "/" + todos.entityCount;}...});
最后,我们再来看一下添加功能的实现。<body>中的第一段内容是这样的:
<p><input c-bind="newItem"><button c-onclick="add()" c-disabled="newItem?false:true">Add</button></p>
这里的<input>绑定到了名为newItem的数据项,用于供用户填写要添加的待办事项。
<button>中c-disabled="newItem?false:true"的作用是声明该按钮只在newItem项的内容不为空时才可用。
add()的具体定义如下:
model.action({...add: function () {model.get("todos").insert({title: model.get("newItem")});model.set("newItem", null);}...});
此处的逻辑其实也非常简单,将newItem中的值取出组装成一条新的待办事项,添加到todos集合中。同时清空newItem数据项的内容。 由于Cola提供的双向数据绑定的特性,我们对数据模型所做的操作都会自动体现到相应的界面显示中。 所以在整个例子的Javascript代码中我们完全看不到直接对于DOM的代码操作。
