环顾四周后,我看到了许多人在敲除手柄 with
绑定方面引起的问题,这特别涉及删除和更换应用with
绑定的元素中的DOM元素。我看到一个案件在"预防"中。从删除DOM元素(quotout.js)和敲除js上的相关问题的绑定。结合困境。我什至在https://github.com/mbest/knockout/issues/9和https://github.com/knockout/knockout/knockout/phockout/pull/476。
我认为,从2.2.0开始的版本有所改进,但是尽管进行了所有这些改进,但我仍然看到一个问题。我已经在http://jsfiddle.net/bluemonkmn/dsp3l/的jsfiddle中证明了这一点。
<div data-bind="with: sampleObj">
<button id="bob" data-bind="text:sampleValue"></button>
<button data-bind="click:$root.update" id="update">Update</button>
</div>
var sample = ko.observable({
sampleValue: "Demo"
});
ko.applyBindings({
sampleObj: sample,
update: function () {
sample({
sampleValue: sample().sampleValue + "x"
});
}
});
bob.onclick = function () {
alert("bob");
};
单击第一个按钮时,警报会弹出。然后单击第二个按钮,该按钮替换了视图模型的值。到目前为止,一切都很好。但是请注意,第一个按钮的事件处理程序已消失,单击它不再显示消息。
我尝试过为"用"绑定的"使用"非常便宜的替代品,如下所示:
ko.bindingHandlers.safeWith = {
'init': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
return { 'controlsDescendantBindings': true };
},
'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var dataValue = ko.utils.unwrapObservable(valueAccessor());
if (dataValue) {
childContext = bindingContext.createChildContext(dataValue);
ko.applyBindingsToDescendants(childContext, element);
}
}
};
这非常适合保留事件处理程序的块中的元素。但是,然后我发现每次发生这种情况时,某些事件处理程序都会增加一倍,因为他们没有删除。我已经在http://jsfiddle.net/bluemonkmn/dsp3l/2/
的更新版本中演示了这一点。单击第一个按钮时,您仍然会收到该消息,即使您单击第二个按钮以更新该值后,它仍会继续工作。但是,如果您再次单击第二个按钮,您会注意到每次更新值时,该事件正在处理的次数都会加倍。
是否有一种简单的方法可以通过实现来解决此问题。我宁愿不喜欢knockout.js
的分叉副本,因为我希望能够跟上最新版本。理想情况下,我只想要一个像withlight
这样的绑定处理程序,它可以独立地站立而无需叉子knockout.js
,它也会反映更新的视图模型的价值而不会丢失事件处理程序。
澄清:在我的真实代码中显示警报的点击事件实际上是一个事件处理程序,与jQuery-ui相似的代码(我相信)附加了一个事件处理程序,您只需调用一个DOM元素上的初始化功能,并调整DOM并设置事件以使Ti像一个不错的控件一样工作。我无法控制该事件的附加方式,除了确定何时称此高级功能设置所有内容。
避免with
绑定选项?
<div>
<button id="bob" data-bind="text: sampleObj().sampleValue"></button>
<button data-bind="click: update" id="update">Update</button>
</div>
update
它看起来与其他控制流绑定(如if,ifnot和foreach)一样,当它们绑定到可观察到的。>
所以我想知道尝试使您的孩子上下文不可观察是可行的吗?例如,而不是这个,
var sample = ko.observable({
sampleValue: "Demo"
});
...尝试更多这样的东西?
var sample = {
sampleValue: ko.observable('Demo')
};
这样,您可观察到的每次都不会被破坏,我们只是在变异价值。这是小提琴:http://jsfiddle.net/vfkr6/1/
...这是代码的样子:
<!-- unchanged from the OP -->
<div data-bind="with: sampleObj">
<button id="bob" data-bind="text:sampleValue"></button>
<button data-bind="click:$root.update" id="update">Update</button>
</div>
// don't make sample observable, only make sample.sampleValue observable
var sample = {sampleValue: ko.observable("Demo")};
ko.applyBindings({
sampleObj: sample,
update: function () { sample.sampleValue(sample.sampleValue() + 'x'); }
});
bob.onclick = function() {alert("bob");};
这正在做您想要的事情,更改子女上下文中按钮的文本,并且不会破坏Bob.onclick事件。