我正在尝试使用自定义bindingHandler来添加类似模板的东西,因此需要自己的模型。 仅供参考(但不需要了解问题):真正的目标是管理位于具有此bindingHandler的DIV内的多个组件。
但是,我无法创建自定义上下文但是让KO无法尝试绑定我创建的元素(并且已经使用自定义bindingHandler对其进行了绑定)。
我得到的只是典型的错误: 未捕获错误:您无法多次将绑定应用于同一元素。
我的猜测是:
Knockout正在执行第一个applyBinding并在其中的元素上搜索绑定处理程序
它执行初始化过程
初始化使用新元素上的applyBindings创建新上下文
完成该操作后,淘汰似乎没有考虑创建的元素(和已经绑定的元素)的“allowBindings:false”并尝试绑定两次事物......
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,它仍然初始化但我无法从中获取model.data属性。
这是我用过的代码的一部分。我只是忘记添加return { controlsDescendantBindings: true };
以防止KO对创建的子元素应用绑定。
它可能无法直接编译,但想法是一样的:在绑定创建的新元素上绑定一个新的childContext,并用当前绑定上下文初始化该项的兄弟。
有了这个,我就能够管理组(div)中的组件,这些组件可以访问父模型(此处未显示的代码,通过$ .closest完成并使用$ .data存储)等等要求自己被附加到模板引用的“panel.list”。
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 };
答案 0 :(得分:4)
从customComponent { controlsDescendantBindings: true }
函数返回init
。
请参阅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
,这种情况下更常用