前兩篇博客已經很清楚的知道knockout.js經過observableArray()數組元素增減,能夠實時的反映在UI上。固然咱們想在數組增長或移除元素時加上自定義邏輯就比如一個觸發器的感受,能夠嗎?javascript
foreach提供了afterAdd及beforeRemove兩個額外的事件,容許在數組新增、移除元素時執行特定邏輯。在此繼續沿用先前的用戶列表呈現範例,加上兩個效果:css
而在ViewModel裏咱們加上兩個函數:html
//添加對象後才觸發,第一次forach並不會觸發 self.afterAddEvent = function (element, index, data) { //經過nodeType過濾,只處理Element Node if (element.nodeType==1) { $(".new").removeClass("new"); $(element).addClass("new"); } }; //注意: beforeRemove事件後,要自已移除被刪除元素 self.beforeRemoveEvent = function (element, index, data) { if (element.nodeType == 1) { $(element) .css("background-color", "#ff6a00") .animate({ opacity: 0.2 },1000, function () { $(this).remove(); }) } };
afterAdd及beforeRemove函數會固定收到三個參數,element、index及data,其中element爲模板容器中的各元素,即:java
<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>
實際運做時afterAdd/beforeRemove會收到不一樣的element被呼叫三次,緣由是除了<tr>以外,<tbody>到<tr>之間的空白、</tr>到</tbody>間的空白也各算一個Element,(FF和chrome是忽略這個空格的)其nodeType爲3即TEXT_NODE,表明TEXT_NODE。所以三次傳入的element分別爲TEXT_NODE、ELEMENT_NODE、TEXT_NODE,而第二次傳入的ELEMENT_NODE是<tr>...</tr>間的內容,纔是咱們須要處理的對象,故加入if (elems.nodeType == 1)的判斷。node
要注意,一旦調用了了beforeRemove,konckout.js就再也不自動幫你移除該筆數據在網頁對應的元素,必須自行處理,但這也提供開發人員絕對的控制權,可自由安排HTML元素要怎麼從網頁上退出。jquery
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index2</title> <style> table { width: 385px } td,th { border: 1px solid #0094ff; text-align: center; } .new { color: #0094ff; background-color:#b6ff00} </style> <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 =ko.observable(name); self.score =ko.observable(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; }); //添加對象後才觸發,第一次forach並不會觸發 self.afterAddEvent = function (element, index, data) { //經過nodeType過濾,只處理Element Node if (element.nodeType==1) { $(".new").removeClass("new"); $(element).addClass("new"); } }; //注意: beforeRemove事件後,要自已移除被刪除元素 self.beforeRemoveEvent = function (element, index, data) { if (element.nodeType == 1) { $(element) .css("background-color", "#ff6a00") .animate({ opacity: 0.2 },600, function () { $(this).remove(); }) } }; }; $(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()))); }); $("#btnUpdateScore").click(function () { vm.users()[vm.users().length-1].score(125).name("HelloWorld!"); }); 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: { data: users, afterAdd: afterAddEvent, beforeRemove: beforeRemoveEvent}"> <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> <input value="Update測試" id="btnUpdateScore" type="button" style="width:200px; background-color:#ff6a00;"/><br/> </section> </section> </body> </html>
備註:chrome
本文版權歸你們共用,不歸本人全部,全部知識都來自於官網支持,書本,國內外論壇,大牛分享等等......後續將學習knockout.js的經常使用功能。數組
若是你喜歡本文的話,推薦共勉,謝謝!app