为什么jQuery UI可拖动会干扰Knockout JS数据绑定



我想了解为什么在下面的代码中将包含的div拖放到jQuery UI中会改变Knockout JS数据绑定的行为。

在第一个div(可拖动)中,对输入框中的文本进行更改并立即单击"保存"不会导致更改反映在可观察对象中。在第二个div(不可拖动)中,变化反映在可观察的:中

<div id='draggable'>
    <h3>Draggable</h3>
    <input data-bind='value: detail'></input>
    <span data-bind='click: saveEdit'>Save</span>
</div>
<div id='fixed'>
    <h3>Fixed</h3>
    <input data-bind='value: detail'></input>
    <span data-bind='click: saveEdit'>Save</span>
</div>

支持以下Javascript:

VM = {
    detail: ko.observable('Cat'),
    saveEdit: function(){
        alert(this.detail()); 
    }
};
$(document).ready(function() {
    $("#draggable").draggable();
    ko.applyBindings(VM);
});

您可以在这个jsFiddle中看到正在运行的代码:http://jsfiddle.net/NLzg2/

如果您将可拖动输入框中的文本更改为Cath并单击"保存",则警报将显示"Cat"。但是,如果在固定输入框中执行相同操作,则警报将显示"Cath"。因此,在第二种情况下,Knockout检测到了值的变化,而在第一种情况下则没有。

我知道我可以通过使用Knockout valueUpdate绑定来强制它在每次按键后更新可观察到的绑定,从而达到预期的效果。像这样:

<input data-bind='value: detail, valueUpdate: "afterkeydown"'></input>

我还知道,如果我改变<span>到<按钮>我得到了我所期望的行为。

我想了解的是,为什么会发生这种情况,以及我如何在不必使用valueUpdate绑定或使用按钮绕过问题的情况下实现我想要的效果(即,可拖动并在其中的元素上具有正常的Knockout值绑定)。

draggable插件捕获鼠标以提供其功能。因此,当你点击span时,插件会处理点击事件,而淘汰不会得到通知。

当您使用button时,它会起作用,因为按钮被排除在可拖动插件的效果之外。

因此,您需要使用cancel选项将spandraggable插件中排除,例如在标记类的帮助下

$("#draggable").draggable({cancel: "input,textarea,button,select,option,.save"});

演示JSFiddle。

最新更新