注意:這是一種高級技術,通常僅在創建可重用綁定的庫時使用。
默認情況下,綁定僅影響它們應用到的元素。 但是如果你想影響所有的后代元素呢?
為此,只需從綁定的init函數中返回{controlsDescendantBindings:true}即可。
示例1:控制是否應用后代綁定
對于一個非常簡單的例子,這里有一個名為allowBindings的自定義綁定,允許后代綁定僅當它的值為true時才應用。 如果值為false,則allowBindings告訴Knockout它負責后代綁定,因此它們不會像往常一樣綁定。
ko.bindingHandlers.allowBindings = { init: function(elem, valueAccessor) { // Let bindings proceed as normal *only if* my value is false var shouldAllowBindings = ko.unwrap(valueAccessor()); return { controlsDescendantBindings: !shouldAllowBindings }; } };
要使此效果生效,以下是一個示例用法:
<div data-bind="allowBindings: true"> <!-- This will display Replacement, because bindings are applied --> <div data-bind="text: 'Replacement'">Original</div> </div> <div data-bind="allowBindings: false"> <!-- This will display Original, because bindings are not applied --> <div data-bind="text: 'Replacement'">Original</div> </div>
示例2:為子孫綁定提供附加值
通常,使用controlsDescendantBindings的綁定也將調用ko.applyBindingsToDescendants(someBindingContext,element)來對一些修改的綁定上下文應用后代綁定。 例如,您可以使用一個名為withProperties的綁定將一些額外的屬性附加到綁定上下文,然后可用于所有后代綁定:
ko.bindingHandlers.withProperties = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { // Make a modified binding context, with a extra properties, and apply it to descendant elements var innerBindingContext = bindingContext.extend(valueAccessor); ko.applyBindingsToDescendants(innerBindingContext, element); // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice return { controlsDescendantBindings: true }; } };
正如你可以看到,綁定上下文有一個擴展函數,產生一個帶有額外屬性的克隆。 extend函數接受具有要復制的屬性的對象或返回此類對象的函數。 函數語法是首選的,以便將來在綁定值中的更改始終在綁定上下文中更新。 此過程不會影響原始綁定上下文,因此不會影響同級元素的危險 - 它只會影響后代。
以下是使用上述自定義綁定的示例:
<div data-bind="withProperties: { emotion: 'happy' }"> Today I feel <span data-bind="text: emotion"></span>. <!-- Displays: happy --> </div> <div data-bind="withProperties: { emotion: 'whimsical' }"> Today I feel <span data-bind="text: emotion"></span>. <!-- Displays: whimsical --> </div>
示例3:在綁定上下文層次結構中添加額外的級別
綁定(如with和foreach)在綁定上下文層次結構中創建額外的級別。 這意味著它們的后代可以通過使用$ parent,$ parents,$ root或$ parentContext來訪問外部級別的數據。
如果你想在自定義綁定中這樣做,那么不使用bindingContext.extend(),使用bindingContext.createChildContext(someData)。 這返回一個新的綁定上下文,其viewmodel是someData,其$ parentContext是bindingContext。 如果需要,您可以使用ko.utils.extend擴展具有額外屬性的子上下文。 例如,
ko.bindingHandlers.withProperties = { init: function(element, valueAccessor, allBindings, viewModel, bindingContext) { // Make a modified binding context, with a extra properties, and apply it to descendant elements var childBindingContext = bindingContext.createChildContext( bindingContext.$rawData, null, // Optionally, pass a string here as an alias for the data item in descendant contexts function(context) { ko.utils.extend(context, valueAccessor()); }); ko.applyBindingsToDescendants(childBindingContext, element); // Also tell KO *not* to bind the descendants itself, otherwise they will be bound twice return { controlsDescendantBindings: true }; } };
這個更新的withProperties綁定現在可以以嵌套方式使用,每個嵌套級別都可以通過$ parentContext訪問父級別:
<div data-bind="withProperties: { displayMode: 'twoColumn' }"> The outer display mode is <span data-bind="text: displayMode"></span>. <div data-bind="withProperties: { displayMode: 'doubleWidth' }"> The inner display mode is <span data-bind="text: displayMode"></span>, but I haven't forgotten that the outer display mode is <span data-bind="text: $parentContext.displayMode"></span>. </div> </div>
通過修改綁定上下文和控制后代綁定,一個強大的和高級的工具來創建自己的自定義綁定機制。
文章列表