你的位置:首页 > Java教程

[Java教程]KnockoutJS 3.X API 第五章 高级应用 控制后代绑定


注意:这是一种高级技术,通常仅在创建可重用绑定的库时使用。

默认情况下,绑定仅影响它们应用到的元素。 但是如果你想影响所有的后代元素呢?

为此,只需从绑定的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>

通过修改绑定上下文和控制后代绑定,一个强大的和高级的工具来创建自己的自定义绑定机制。