您不僅限于使用內置的綁定,如click,value綁定等,您可以創建自己的綁定。 這是如何控制視圖模型如何與DOM元素進行交互,并且為您提供了大量的靈活性,以便于以復用的方式封裝復雜的行為。
注冊綁定
要注冊綁定,請將其作為ko.bindingHandlers的子屬性添加,比如如下例子:
ko.bindingHandlers.yourBindingName = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { // 這是首次運行綁定的初始化回調函數 // 在此處設置初始狀態和事件處理程序
}, update: function(element, valueAccessor, allBindings, viewModel, bindingContext) { // 當綁定首次應用到元素時,將調用一次
// 每當監控屬性/計算屬性的值發生變化時 // 每當DOM綁定的元素值方法變化時被調用. } };
然后你可以使用它在任何數量的DOM元素:
<div data-bind="yourBindingName: someValue"> </div>
注意:你實際上不必提供完整的init和update回調 - 你可以只提供一個或另一個。
‘update’回調函數
當綁定應用于元素并跟蹤您訪問的任何依賴性(observables / computeds)時,Knockout將最初調用update回調。 當任何這些依賴關系改變時,將再次調用update回調。 將以下參數傳遞給它:
element
— 此綁定中涉及的DOM元素valueAccessor
— 可以調用的JavaScript函數,以獲取此綁定中涉及的當前模型屬性。 調用此函數而不傳遞任何參數(即調用valueAccessor())以獲取當前模型屬性值。 要容易接受observable和plain值,請對返回的值調用ko.unwrap。allBindings
—可用于訪問綁定到此DOM元素的所有模型值的JavaScript對象。 調用allBindings.get('name')檢索名稱綁定的值(如果綁定不存在則返回undefined); 或allBindings.has('name')來確定當前元素是否存在名稱綁定。viewModel
— 此參數在Knockout 3.x中已棄用。 使用bindingContext。$ data或bindingContext $ raw用于訪問視圖模型的數據。bindingContext
— 保存可用于此元素的綁定的綁定上下文的對象。 此對象包括特殊屬性,包括$ parent,$ parents和$ root,可用于訪問與此上下文的祖先綁定的數據。
例如,您可能已經使用可見綁定控制元素的可見性,但現在您想要進一步進行和動畫轉換。 您希望元素根據observable的值滑入和滑出存在。 你可以通過編寫調用jQuery的slideUp / slideDown函數的自定義綁定來實現:
源碼:
<div data-bind="slideVisible: giftWrap, slideDuration:600">You have selected the option</div> <label><input type="checkbox" data-bind="checked: giftWrap" /> Gift wrap</label> <script type="text/javascript"> var viewModel = { giftWrap: ko.observable(true) }; ko.bindingHandlers.slideVisible = { update: function(element, valueAccessor, allBindings) { // First get the latest data that we're bound to var value = valueAccessor(); // Next, whether or not the supplied model property is observable, get its current value var valueUnwrapped = ko.unwrap(value); // Grab some more data from another binding property var duration = allBindings.get('slideDuration') || 400; // 400ms is default duration unless otherwise specified // Now manipulate the DOM element if (valueUnwrapped == true) $(element).slideDown(duration); // Make the element visible else $(element).slideUp(duration); // Make the element invisible } }; ko.applyBindings(viewModel); </script>
當然,乍一看很多的代碼,但一旦你創建了你的自定義綁定,他們可以很容易地重用在許多地方。
‘init’回調函數
Knockout將為您使用綁定的每個DOM元素調用一次init函數。 init有兩個主要用途:
- 為DOM元素設置初始狀態
- 注冊任何事件處理程序,例如,當用戶單擊或修改DOM元素時,可以更改關聯的可觀察事件的狀態
KO將傳遞給init的參數和update回調具有完全相同的參數集。
繼續前面的示例,您可能希望使用slideVisible將元素設置為在頁面第一次出現時立即可見或不可見(沒有任何動畫幻燈片),以便動畫只在用戶更改模型狀態時運行。 你可以這樣做:
源碼:
ko.bindingHandlers.slideVisible = { init: function(element, valueAccessor) { var value = ko.unwrap(valueAccessor()); // Get the current value of the current property we're bound to $(element).toggle(value); // jQuery will hide/show the element depending on whether "value" or true or false }, update: function(element, valueAccessor, allBindings) { // Leave as before } };
這意味著如果giftWrap被定義為初始狀態為false(即,giftWrap:ko.observable(false)),則相關聯的DIV最初將被隱藏,然后當用戶稍后檢查該框時滑入視圖。
在DOM事件后修改observable
您已經了解如何使用udpate,以便在監控屬性的更改時,可以更新關聯的DOM元素。 但是在另一個方向的事件呢? 當用戶對DOM元素執行某些操作時,您可能需要更新關聯的監控屬性。
您可以使用init回調作為注冊事件處理程序的地方,這將對關聯的observable進行更改。 例如
Name:
源碼:
<p>Name: <input data-bind="hasFocus: editingName" /></p> <!-- Showing that we can both read and write the focus state --> <div data-bind="visible: editingName">You're editing the name</div> <button data-bind="enable: !editingName(), click:function() { editingName(true) }">Edit name</button> <script type="text/javascript"> var viewModel = { editingName: ko.observable() }; ko.bindingHandlers.hasFocus = { init: function(element, valueAccessor) { $(element).focus(function() { var value = valueAccessor(); value(true); }); $(element).blur(function() { var value = valueAccessor(); value(false); }); }, update: function(element, valueAccessor) { var value = valueAccessor(); if (ko.unwrap(value)) element.focus(); else element.blur(); } }; ko.applyBindings(viewModel,document.getElementById('eq3')); </script>
現在,您可以通過將元素綁定到可監控對象來讀取和寫入元素的“焦點”。
備注,虛擬綁定
如果您希望自定義綁定可用于Knockout虛擬元素語法,可使用如下寫法:
<!-- ko mybinding: somedata --> ... <!-- /ko -->
文章列表