"if" 和 "with" 绑定处理程序导致所有事件处理程序丢失(即使使用 jQuery 的 on() 创建)
"if" and "with" binding handlers causing all event handlers to be lost (even if created with jQuery's on())
我正在使用 KnockoutJS,我注意到一个绑定问题,我可以用这个例子来解释:
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="if: displayMessage">Here is a message.<span id="super">SUPER</span> Astonishing.</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
$(function(){
ko.applyBindings({
displayMessage: ko.observable(true)
});
$('#super').on("click", function(){
alert('SUUUUUPER');
});
});
当您第一次单击 "SUPER" span
元素时,会出现警报。但是,如果您通过将模型的 属性 displayMessage
设置为 false
并将其放回 true
以再次显示它来删除块,则绑定到点击事件是不再工作。
从if
、ifnot
和with
bindingHandlers的源代码我知道knockout删除了DOM clone并保存它第一次并重新追加它使用虚拟元素 API.
所以我的问题是:知道 jQuery on()
实用程序将事件处理程序附加到所选元素,即使它们尚不存在。是使用导致点击绑定丢失的虚拟元素。如果不是:向我解释会发生什么。
我不会在带有 KO 控制标记的元素上使用 id
。问题是:Knockout 将克隆元素、重组 DOM 等,您最终可能会得到多个具有相同 id
的元素,这是无效的,从那时起基于 ID 的浏览器行为是不可预测的.
此外,因为 if
绑定 KO 会 remove/add DOM 节点在运行中,你需要 this advice 来确保 jQuery on
函数也处理新创建的元素。
这是一个使用 class
而不是 id
的不同版本,它按预期工作:
$(function(){
ko.applyBindings({
displayMessage: ko.observable(true)
});
$(document.body).on("click", ".super", function(){
alert('SUUUUUPER');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="if: displayMessage">Here is a message.<span class="super">SUPER</span> Astonishing.</div>
注意:
- 您也可以使用
visible
绑定,这 可能 避免需要提到的 on
-建议。
- 您应该尽量避免使用 jQuery 进行此类事件处理,而应改用 Knockout 的 MVVM 式事件处理(利用
click
绑定)。
我正在使用 KnockoutJS,我注意到一个绑定问题,我可以用这个例子来解释:
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="if: displayMessage">Here is a message.<span id="super">SUPER</span> Astonishing.</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
$(function(){
ko.applyBindings({
displayMessage: ko.observable(true)
});
$('#super').on("click", function(){
alert('SUUUUUPER');
});
});
当您第一次单击 "SUPER" span
元素时,会出现警报。但是,如果您通过将模型的 属性 displayMessage
设置为 false
并将其放回 true
以再次显示它来删除块,则绑定到点击事件是不再工作。
从if
、ifnot
和with
bindingHandlers的源代码我知道knockout删除了DOM clone并保存它第一次并重新追加它使用虚拟元素 API.
所以我的问题是:知道 jQuery on()
实用程序将事件处理程序附加到所选元素,即使它们尚不存在。是使用导致点击绑定丢失的虚拟元素。如果不是:向我解释会发生什么。
我不会在带有 KO 控制标记的元素上使用 id
。问题是:Knockout 将克隆元素、重组 DOM 等,您最终可能会得到多个具有相同 id
的元素,这是无效的,从那时起基于 ID 的浏览器行为是不可预测的.
此外,因为 if
绑定 KO 会 remove/add DOM 节点在运行中,你需要 this advice 来确保 jQuery on
函数也处理新创建的元素。
这是一个使用 class
而不是 id
的不同版本,它按预期工作:
$(function(){
ko.applyBindings({
displayMessage: ko.observable(true)
});
$(document.body).on("click", ".super", function(){
alert('SUUUUUPER');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<label><input type="checkbox" data-bind="checked: displayMessage" /> Display message</label>
<div data-bind="if: displayMessage">Here is a message.<span class="super">SUPER</span> Astonishing.</div>
注意:
- 您也可以使用
visible
绑定,这 可能 避免需要提到的on
-建议。 - 您应该尽量避免使用 jQuery 进行此类事件处理,而应改用 Knockout 的 MVVM 式事件处理(利用
click
绑定)。