KnockoutJS 3.X API 第五章 高級應用(3) 虛擬元素綁定
注意:這是一種高級技術,通常僅在創建可重用綁定的庫時使用。 這不是你通常需要做的時候使用Knockout構建應用程序。
Knockout的控制流綁定(例如,if和foreach)不僅可以應用于常規DOM元素,而且可以應用于由基于特殊注釋的語法定義的“虛擬”DOM元素。 例如:
<ul> <li class="heading">My heading</li> <!-- ko foreach: items --> <li data-bind="text: $data"></li> <!-- /ko --> </ul>
自定義綁定也可以與虛擬元素一起使用,但要啟用此功能,必須通過使用ko.virtualElements.allowedBindings API明確告知Knockout您的綁定理解虛擬元素。
示例
為了開始,這里是一個自定義綁定,隨機化DOM節點的順序:
ko.bindingHandlers.randomOrder = { init: function(elem, valueAccessor) { // Pull out each of the child elements into an array var childElems = []; while(elem.firstChild) childElems.push(elem.removeChild(elem.firstChild)); // Put them back in a random order while(childElems.length) { var randomIndex = Math.floor(Math.random() * childElems.length), chosenChild = childElems.splice(randomIndex, 1); elem.appendChild(chosenChild[0]); } } };
<div data-bind="randomOrder: true"> <div>First</div> <div>Second</div> <div>Third</div> </div>
但是,它不適用于虛擬元素。 如果您嘗試以下操作:
<!-- ko randomOrder: true --> <div>First</div> <div>Second</div> <div>Third</div> <!-- /ko -->
...那么你會得到錯誤綁定的“randomOrder”不能與虛擬元素一起使用。 讓我們解決這個問題。 要使randomOrder可用于虛擬元素,請先通知Knockout允許它。 添加以下內容:
ko.virtualElements.allowedBindings.randomOrder = true;現在不會有錯誤。 但是,它仍然無法正常工作,因為我們的randomOrder綁定是使用不理解虛擬元素的普通DOM API調用(firstChild,appendChild等)編碼的。 這就是為什么KO要求你明確選擇加入虛擬元素支持的原因:除非你的自定義綁定是使用虛擬元素API編碼的,否則它不會正常工作!
讓我們更新randomOrder的代碼,這次使用KO的虛擬元素API:
ko.bindingHandlers.randomOrder = { init: function(elem, valueAccessor) { // Build an array of child elements var child = ko.virtualElements.firstChild(elem), childElems = []; while (child) { childElems.push(child); child = ko.virtualElements.nextSibling(child); } // Remove them all, then put them back in a random order ko.virtualElements.emptyNode(elem); while(childElems.length) { var randomIndex = Math.floor(Math.random() * childElems.length), chosenChild = childElems.splice(randomIndex, 1); ko.virtualElements.prepend(elem, chosenChild[0]); } } };
請注意,我們現在使用的是ko.virtualElements.firstChild(domOrVirtualElement),而不是使用像domElement.firstChild之類的API。 randomOrder綁定現在將正確地使用虛擬元素,例如<! - ko randomOrder:true - > ... <! - / ko - >。
此外,randomOrder仍將使用常規DOM元素,因為所有ko.virtualElements API都與常規DOM元素向后兼容。
Virtual Element APIs(虛擬元素API)
Knockout提供了以下用于處理虛擬元素的功能。
-
ko.virtualElements.allowedBindings一個對象的鍵確定哪些綁定可與虛擬元素一起使用。 設置ko.virtual Elements.allowed Bindings.mySuper Binding = true以允許mySuperBinding與虛擬元素一起使用。
-
ko.virtualElements.emptyNode(containerElem)從真實或虛擬元素容器Elem中刪除所有子節點(清除與其關聯的任何數據,以避免內存泄漏)。
-
ko.virtualElements.firstChild(containerElem)返回實元素或虛擬元素容器元素的第一個子元素,如果沒有子元素,則返回null。
-
ko.virtualElements.insertAfter(containerElem, nodeToInsert, insertAfter)插入節點插入作為實際或虛擬元素容器Elem的子元素,緊接在insertAfter之后的位置(其中insertAfter必須是containerElem的子元素)。
-
ko.virtualElements.nextSibling(node)返回在其真實或虛擬父元素中跟隨節點的兄弟節點,如果沒有下一個兄弟節點,則返回null。
-
ko.virtualElements.prepend(containerElem, nodeToPrepend)將nodePrepend插入為實元素或虛擬元素containerElem的第一個子元素。
-
ko.virtualElements.setDomNodeChildren(containerElem, arrayOfNodes)從真實或虛擬元素containerElem中刪除所有子節點(在此過程中,清除與其關聯的任何數據以避免內存泄漏),然后將所有節點fromarrayOfNodes作為其新子節點插入。
請注意,這并不意味著完全替代了一整套常規DOM API。 Knockout僅提供一組最小的虛擬元素API,以便在執行控制流綁定時執行所需的各種轉換。

浙公網安備 33010602011771號