我有几个在DOM加载或文档就绪时创建的jquery dom事件。这些主要是默认行为,应该应用于我的应用程序中的所有表单。例如:
$('input:text').focus(function ()
{
$(this).select();
});
在应用淘汰赛绑定之前,我可以检查我的dom元素,所有事件都在那里:
但是当我运行applyBindings方法将viewmodel绑定到我的DOM时,"with" binding会删除与knockout无关的所有事件:
我已尝试按照documentation和this answer上的说明覆盖 cleanExternalData 。但是这对此没有帮助,函数被替换,但是当在绑定过程中应用模板时,事件仍然从DOM中删除。
对于记录,这不是 with 函数的独占行为,但所有匿名模板函数也会执行此操作,foreach,if,ifnot。正如预期的那样,使用模板也可以采用相同的方式。 DOM元素被完全销毁,存储为模板,然后在条件满足时再次添加到我的文档中,但现在没有任何jquery事件处理程序。
如何避免敲除从DOM元素中删除事件?
答案 0 :(得分:1)
您可以使用数据绑定来使用jquery on()功能来处理事件,而不是将元素绑定到特定节点。这是我使用的绑定:
define(['knockout'], function (ko) {
ko.bindingHandlers.eventListener = {
init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
var params = ko.utils.unwrapObservable(valueAccessor());
if (!(params instanceof Array)) {
params = [params];
}
params.forEach(function (param) {
$(element).on(param.event, param.selector, function (event) {
param.callback(ko.dataFor(this), ko.contextFor(this), event);
});
});
}
}
});
用法:
<div data-bind="eventListener: [
{ event: 'click', selector: '.copyInclusionRule', callback: copyInclusionRule},
{ event: 'click', selector: '.deleteInclusionRule', callback: deleteInclusionRule}]">
... other knockout template stuff here ...
</div>
以上内容将侦听具有指定类的元素上的单击事件,并在div的“范围”内的任何内容收到事件时执行回调。 'event'param的值可以是on()使用的任何值。
我认为你无法利用cleanNode覆盖的原因是你的dom被完全破坏并重新创建..至少这是我的理论,如果有办法获得某种内存ID pre-applyBindings()dom元素然后在调用applyBindings之后,是那些新节点?如果它们是新节点,那么你无法通过清理解决这些问题,那些节点就不复存在了。
答案 1 :(得分:0)
好的,这就是我如何解决我的问题,我希望这可以向其他不想破坏他们的DOM的人澄清事情。如果您不希望敲除破坏DOM,那么从版本2.2开始就可以实现。因此,在不需要的情况下销毁DOM不是预期的行为,可以避免。
之前我曾尝试过几次由Michael Best创建的出价,例如他的using binding that will come in knockout 3.5,以及let或withLight(现在变为使用)。没有真正有效。这些简化的出价将加载初始对象,但在此对象属性发生更改时不会更新dom。
但这帮助我弄清楚我做错了什么。当我想更新我的可观察对象时,我正在使用 myViewModel.observableObject(NewObject),就像documentation告诉我要做的那样:
要向observable写入新值,请调用observable并将新值作为参数传递。例如,调用 myViewModel.personName('Mary')会将名称值更改为“Mary”。
但是我没有传递单个属性的值,我传递的是一个具有相同结构(相同属性)的新对象。这引发了淘汰旧物体被摧毁(因此,虚伪一秒钟)和一个新物体取而代之,即使所有属性都在那里,它们只有不同的值。与文档告诉我的不同,它不仅仅是更改了值,而是更改了整个对象。
要解决这个问题,不要这样做,首先,我必须使用虚拟数据启动我已创建此对象的viewModel,这使得当调用 applyBindings 时,淘汰不会破坏DOM。然后,当我想要更新对象时,我将可观察对象的每个属性的值替换为具有新对象的值。这没有破坏对象和淘汰赛正确更新我的绑定。
myViewModel.setSelectedItem = function setSelectedItem (newObject)
{
for (var prop in myViewModel.myObservableObject())
myViewModel.myObservableObject()[prop](newObject[prop]);
}
with 绑定仍然会杀死我的一些事件(例如,我的某个组件的角度ng-change),但它保留了所有jquery事件(这很棒)。并且using绑定根本没有杀死我的任何事件(甚至更好)。