以列表方式呈現資料
處理以陣列形式儲存的多條資料,要先認識foreach。在ViewModel定義一個JavaScript Array或是ko.observableArray() (observableArray在新增或剔除陣列元素時,KO會立刻察覺反應到UI,普通Array則不會),然後在某個容器元素(例如: div, ul, tbody... )宣告data-bind="foreach: arrayPropName",就可以指定KO將容器內的子元素模板(Template)就會對陣列物件的資料自動迴圈遍歷,例如:
<tbody data-bind="foreach: users"> <tr> <td><span data-bind="text: id"></span></td> <td><span data-bind="text: name"></span></td> <td><span data-bind="text: score" style='text-align: right'></span></td> <td><a href='#' data-bind="click: $root.removeUser">移除</a></td> </tr> </tbody>
在上面的例子中,我們假設ViewModel有一個陣列屬性—users,其中每筆資料物件都有id, name, score三個屬性,在tbody上宣告data-bind="foreach: users",意味者<tbody>到</tbody>間的內容,會依users陣列的元素多寡重複出現n次。而其中元素(如<span>, <a>)繫結物件便是users中的每一條使用者資料,因此只要寫上data-bind="text: id"就可以對應到使用者的id屬性。最後一個<td>中出現了<a data-bind="click: $root.removeUser">,你一定可以猜想它可用來移除該使用者資料,$root是一個特殊變數,會指向ViewModel個體。在這裡必須加上的原因是我們在ViewModel定義了remoteUser方法,但在<tbody>中,預設繫結的物件是users物件,若只寫data-bind="click: removeUser",KO會誤認成users物件上的removeUser方法。加上$root,KO會改由ViewModel的最上層尋找removeUser方法。
removeUser的定義如下:
self.removeUser = function(user) { self.users.remove(user); }
當它在foreach範圍被點選觸發時,會接收到一個引數,指向被點選的那條資料物件。所以,只需self.users.remove(user)就可以將該條資料從observableArray移除,網頁也會馬上做出迴應,該條資料的<tr>會立刻從<tbody>中消失。
如果要新增使用者資料,在observableArray中加入一條具有id, name, score三個屬性的物件即可,為了規範元件包含所有必要屬性,我們將user定義成function模擬ViewModel形式的物件:
function UserViewModel(id, name, score) { var self = this; self.id = id; self.name = name; self.score = score; }
如此新增資料時即可寫成viewModel.users.push(new UserViewModel("0001", "halower", 125)),為了展現KO可以實時監控obervableArray的風吹草動,我們寫一個ko.computed計算所有使用者的score總和:
self.totalScore = ko.computed(function () { var total = 0; $.each(self.users(), function (i, u) { total += u.score; }); return total; });
共 <span data-bind="text: users().length"></span> 條, 合計 <span data-bind="text: totalScore"></span> 分
完整程式碼如下:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index2</title> <script src="~/Scripts/jquery-2.0.3.js"></script> <script src="~/Scripts/knockout-2.3.0.js"></script> <script type="text/javascript"> //定義user資料物件 function UserViewModel(id,name,score) { var self = this; self.id = id; self.name = name; self.score = score; } //定義ViewModel function ViewModel() { var self = this; self.users = ko.observableArray();//新增動態監視陣列物件 self.removeUser = function (user) { self.users.remove(user); } self.totalscore = ko.computed(function () { var total = 0; $.each(self.users(), function (i, u) { total += u.score; }) return total; }); }; $(function () { var vm = new ViewModel(); //預先新增一些資料 vm.users.push(new UserViewModel("d1", "rohelm", 121)); vm.users.push(new UserViewModel("d2", "halower", 125)); $("#btnAddUser").click(function () { vm.users.push(new UserViewModel( $("#u_id").val(), $("#u_name").val(), parseInt($("#u_score").val()))); }); ko.applyBindings(vm); }); </script> </head> <body> <section style="margin:250px"> <section> ID<input type="text" id="u_id" style="width:30px"> Name<input type="text" id="u_name" style="width:30px"> Score<input type="text" id="u_score" style="width:30px"><br/> <input value="Add" id="btnAddUser" type="button" style="width:200px; background-color:#ff6a00;"/><br/> 共 <span data-bind="text: users().length"></span> 條--------------合計 <span data-bind="text: totalscore"></span> 分 </section> <section> <table> <thead> <tr><th>ID</th><th>Name</th><th>Score </th><th>Option</th></tr> </thead> <tbody data-bind="foreach: users"> <tr> <td><span data-bind="text: id"></span></td> <td><span data-bind="text: name"></span></td> <td><span data-bind="text: score"></span></td> <td><a href='#' data-bind="click: $root.removeUser">Remove</a></td> </tr> </tbody> </table> </section> </section> </body> </html>
效果演示:
備註:
本文版權歸大家共用,不歸本人所有,所有知識都來自於官網支援,書本,國內外論壇,大牛分享等等......後續將學習knockout.js的常用功能。
如果你喜歡本文的話,推薦共勉,謝謝!