文章出處

注意:這是一種高級技術,通常僅在創建可重用綁定的庫時使用。

默認情況下,綁定僅影響它們應用到的元素。 但是如果你想影響所有的后代元素呢?

為此,只需從綁定的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>

通過修改綁定上下文和控制后代綁定,一個強大的和高級的工具來創建自己的自定義綁定機制。


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()