翻譯:Knockout 快速上手 - 5: 你需要知道的頂級(jí)特性 續(xù)UtilitiesKnockout 提供了許多可以你開發(fā)中使用的工具,你可以在 ko.utils 命名空間中找到它們,我最喜歡的工具如下所示:
下面的代碼演示了使用方法。 // extend usage var a = { val: 1 }, b = { val: 2 }; ko.utils.extend(a, b); console.log(a.val); // console: 2 // unwrapObservable usage var c = ko.observable(99), d = 98; console.log(ko.utils.unwrapObservable(c)); // console: 99 console.log(ko.utils.unwrapObservable(d)); // console: 98 // array "map" utility function usage var arr = [100, 101]; var mapped = ko.utils.arrayMap(arr, function (item) { return item + 50; }) console.log(arr); // console: [ 150, 151 ] Data-bind statements我們一直關(guān)注 Knockout 的腳本庫(kù),實(shí)際上,Knockout 被設(shè)計(jì)為可以簡(jiǎn)單地將 JavaScript 對(duì)象綁定到 HTML 中。API 使用與 HTML5 兼容的 data-bind 語(yǔ)法。在我們前面的示例中,你可以看到可以簡(jiǎn)單地將 HTML 元素的屬性綁定到 ViewModel 的屬性上。data-bind 語(yǔ)法允許使用逗號(hào)分隔的綁定定義,下面的示例演示了使用方式。 <span data-bind="text: myText"></span> <div data-bind="visible: isVisible, with: someProp"></div> <input data-bind="value: someVal, css: { 'error': !someVal.isValid(), 'success': someVal.isValid() }"/> Applying bindingsapplyBindings 是 Knockout 一切工作啟動(dòng)的起點(diǎn)。大多數(shù)的示例都演示了將一個(gè) ViewModel 作為參數(shù)的使用方式。但是你可以通過(guò)第二個(gè)參數(shù)來(lái)指定一個(gè) DOM 對(duì)象,Knockout 將只會(huì)綁定到這個(gè) DOM 節(jié)點(diǎn)及其子節(jié)點(diǎn)上。 多數(shù)的應(yīng)用只有一個(gè) ViewModel ,在調(diào)用 applyBinding 的時(shí)候,也僅僅傳遞一個(gè) ViewModel 參數(shù)。但是,我創(chuàng)建過(guò)許多復(fù)雜的應(yīng)用程序,在一個(gè)頁(yè)面中使用了多個(gè) ViewModel 對(duì)象,使用多個(gè) ViewModel 的分別處理提示,設(shè)置,還有當(dāng)前用戶的信息等等。在這些情況下,通過(guò)限制 Knockout 綁定的節(jié)點(diǎn)數(shù)量,可以獲取性能的優(yōu)勢(shì)。如果你僅僅需要更新頁(yè)面的部分內(nèi)容,就不要通過(guò) Knockout 綁定到整個(gè)頁(yè)面上。 Binding handlers我曾經(jīng)提到過(guò) Knockout 提供了許多的擴(kuò)展點(diǎn)。有一些比 Knockout 的 Binding handler 更方便。雖然通過(guò) data-bind 語(yǔ)法實(shí)現(xiàn)了 binding handler 。Knockout 還允許我們自定義綁定的處理器,所以,我們可以實(shí)現(xiàn),或者重寫,我們自定義的功能。 在 MVVM 風(fēng)格的開發(fā)中, 我們會(huì)有兩種類型的綁定:?jiǎn)蜗蚝碗p向綁定。單向的綁定是簡(jiǎn)單的信息讀取,將 ViewModel 中的數(shù)據(jù)讀取出來(lái)綁定到 DOM 中。你可以想像出雙向的數(shù)據(jù)綁定就是在單向的基礎(chǔ)之上,將 DOM 對(duì)象的更新返回到 ViewModel 的屬性上。Knockout 允許我們創(chuàng)建所有類型的綁定,下面的代碼演示了基本處理器使用。 ko.bindingHandlers['myHandler'] = { init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { }, update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { } }; 如你所見,我們提供了兩個(gè)鉤子來(lái)實(shí)現(xiàn)我們的邏輯。Init 和 update 函數(shù)。這些函數(shù)的參數(shù)如下所示:
你可以在想,這些東西看起來(lái)都差不多,我們應(yīng)該在哪里實(shí)現(xiàn)我們的業(yè)務(wù)邏輯呢?init 函數(shù)僅僅在調(diào)用 applyBinding 的時(shí)候調(diào)用一次。Knockout 遍歷整個(gè) DOM 樹,查找 data-bind 語(yǔ)法,處理它們,在每個(gè)需要的綁定上,調(diào)用 init 方法。然后,在調(diào)用 init 方法之后,立即調(diào)用 update 方法,以后,在綁定發(fā)生變化的時(shí)候會(huì)多次調(diào)用這個(gè)方法 ( 如果是 Subscribable )。 我的處理方式是在 init 中注冊(cè)我所有的事件處理器 ( change, blur, focus ) ,然后在 update 中處理 HTML。 下面的代碼演示了常見的單向綁定,這個(gè)例子與 visible 正好相反,我們可以使用 isHidden 而不是 isVisible。 // invisible -> the inverse of 'visible' ko.bindingHandlers['invisible'] = { update: function (element, valueAccessor) { var newValueAccessor = function () { // just return the opposite of the visible flag! return !ko.utils.unwrapObservable(valueAccessor()); }; return ko.bindingHandlers.visible.update(element, newValueAccessor); } }; 下面的代碼演示了雙向的綁定,這個(gè)例子演示對(duì)一個(gè)數(shù)字的驗(yàn)證,從元素中獲取數(shù)據(jù)傳遞到 ViewModel,在 ViewModel 發(fā)生變化的時(shí)候也可以傳遞到 DOM。 // simple number parsing function parseNumber(strVal){ return parseInt(strVal, 10); } // very basic two-way binding handler ko.bindingHandlers['number'] = { init: function (element, valueAccessor, allBindingsAccessor) { //handle the input changing ko.utils.registerEventHandler(element, "change", function () { var observable = valueAccessor(); var number = parseNumber(element.value); if (number !== NaN) { observable(element.value); } }); }, update: function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); var number = parseNumber(value); if (number !== NaN) { element.setAttribute("value", number); } } }; |
|
來(lái)自: 昵稱10504424 > 《工作》