Knockout自定义bindingHandler不能在附加元素上应用bindings
Knockout custom bindingHandler cannot applyBindings on appended elements
我试图使用一个自定义bindingHandler,它添加了一个类似模板的东西,因此需要自己的模型。仅供参考(但不是理解问题所必需的):真正的目标是管理位于具有此bindingHandler的DIV中的几个组件。
然而,我无法创建一个自定义上下文,但要阻止KO尝试绑定我创建的元素(并且已经使用自定义bindingHandler对其应用了绑定)。
我得到的是典型的错误:未捕获错误:不能对同一元素多次应用绑定。
会发生什么?
我猜是:
-
Knockout正在执行第一个applyBinding并搜索其中元素的绑定处理程序
-
执行初始化过程
-
初始化用新元素的applyBindings创建一个新的上下文
-
在该操作完成后,knockout似乎没有考虑到创建元素(和已经绑定的元素)上的"allowBindings:false",并尝试绑定两次……
<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
返回值之外,我还做了以下更改:
- 删除
- 修正
data="text: data"
应该是data-bind="text: data"
- 将新元素的
ko.applyBindings
更改为ko.applyBindingsToDescendants
,这在这种情况下更常用
allowBindings: false
- 编写脚本以循环遍历数组并为DOM元素应用值
- 对每个元素应用不同的 CSS
- 将新元素作为指令的默认元素应用
- 仅对一个元素应用设置间隔
- 如果单词出现第 n 次,则对元素应用更改
- 为每个 DOM 元素应用随机 CSS
- 获取一个元素的宽度,并相对于第一个元素应用于另一个元素
- 对子元素应用悬停效果
- 使用纯javascript获取li元素onclick,而不对每个元素应用onclick
- 将数组的元素应用于函数javascript
- 对td元素应用填充引发异常
- 如何为JavaScript附加的DOM元素应用类似live()的功能
- D3.js -有条件地对数组元素应用nest.key()函数
- 对一组元素应用angular指令
- 如何使用min/max-height和height为元素应用响应式CSS高度
- 对未选中的元素应用样式
- 对所有带有id的元素应用JavaScript
- 如何为多个元素应用jquery悬停
- 动态地对:before元素应用样式
- 如果draggable元素应用了转换,Jquery的draggable containment将不起作用