Knockout自定义bindingHandler不能在附加元素上应用bindings

Knockout custom bindingHandler cannot applyBindings on appended elements

本文关键字:元素 应用 bindings 自定义 bindingHandler 不能 Knockout      更新时间:2023-09-26

我试图使用一个自定义bindingHandler,它添加了一个类似模板的东西,因此需要自己的模型。仅供参考(但不是理解问题所必需的):真正的目标是管理位于具有此bindingHandler的DIV中的几个组件。

然而,我无法创建一个自定义上下文,但要阻止KO尝试绑定我创建的元素(并且已经使用自定义bindingHandler对其应用了绑定)。

我得到的是典型的错误:未捕获错误:不能对同一元素多次应用绑定。

会发生什么?

我猜是:

  • Knockout正在执行第一个applyBinding并搜索其中元素的绑定处理程序

  • 执行初始化过程

  • 初始化用新元素的applyBindings创建一个新的上下文

  • 在该操作完成后,knockout似乎没有考虑到创建元素(和已经绑定的元素)上的"allowBindings:false",并尝试绑定两次……

代码(jsfiddle)http://jsfiddle.net/darknessm0404/tB6Zv/3/

<div id="view">
    viewModel content.
    <p data-bind="text:data"></p>
    <div data-bind="customComponent:{}">
        <p>Need to have is own model. Another element is added while the constructor of the viewModel is instancied.</p>
    </div>
</div>

,

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 };
    }
};
ko.bindingHandlers.customComponent = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
            // Append new element
            var $component = $('<div data-bind="allowBindings:false">customComponent content: <span data="text:data"></span><div>').appendTo($(element));
            // Apply bindings on newly created element
            console.log('2.A. customComponent -> applyBindings -> started');
            ko.applyBindings({
                data: 'COMPONENT MODEL DATA'
            }, $component[0]);
            console.log('2.A. customComponent -> applyBindings -> completed');
        }
};
console.log('1.A. view -> applyBindings -> started');
ko.applyBindings({
    data: 'VIEW MODEL DATA'
}, $('#view')[0]);
console.log('1.B. view -> applyBindings -> completed');

如何使其工作通过说敲除,以防止绑定这些已经绑定的项目?

如何强制knockout不解析这些已经绑定的项?我试图将allowBindings:false添加到包含"customComponent:…"的DIV,它仍然初始化,但我无法获得模型。


解决方案

这是我使用的一部分代码。我只是忘记添加return { controlsDescendantBindings: true };以防止KO在创建的子元素上应用绑定。

它可能不直接编译,但思想是一样的:在绑定创建的新元素上绑定一个新的childContext,并用当前绑定上下文初始化该项的兄弟项。

这样,我就能够管理组(div)中的组件,这些组件可以访问父模型(这里没有显示代码,它是通过$完成的)。最近和存储的东西用$.data),所以要求自己被附加到"面板"。

 init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        //...
        // Template creation
        var $template = $('<ul></ul>').prependTo($(element));
        Quadratus.ko.dataBind($template, {
            foreach: 'panel.list'
        });
        $('<li><span data-bind="text:''hello''"></span></li>').appendTo($template);
        ko.applyBindings(bindingContext.createChildContext(model), $template[0]);
        $template.siblings().each(function () {
            // Apply current bindingcontext on siblings
            ko.applyBindings(bindingContext, this);
        });
 return { controlsDescendantBindings: true };

从customComponent init函数返回{ controlsDescendantBindings: true }

见http://knockoutjs.com/documentation/custom-bindings-controlling-descendant-bindings.html

这是一个更新您的小提琴:http://jsfiddle.net/tB6Zv/4/

除了添加controlsDescendantBindings返回值之外,我还做了以下更改:

    删除allowBindings: false
  • 修正data="text: data"应该是data-bind="text: data"
  • 将新元素的ko.applyBindings更改为ko.applyBindingsToDescendants,这在这种情况下更常用