如何让 DOM/event 听众知道新添加的节点?
How do I make DOM/event listeners aware of newly appended nodes?
TL;DR:
我使用 $(..).append(node)
,但不考虑包含新添加的节点,尽管它们(假定)匹配 jQuery select 或
问题
我在下面有一些代码使用复选框但模拟单选按钮的行为。换句话说,任何时候都只能(有效地)select 编辑一个复选框。不应超过一个 selected。
如果您 运行 下面的示例并单击前 3 个复选框,它们将像单选按钮一样工作。无论您点击多少,都只会 selected。
但是,如果你添加点,新添加的点将不会被JS考虑,即使理论上它也应该抓住它们...
具体来说:您可以select新添加的复选框,它将select添加到已经select的复选框中之前。这是不正确的,因为任何时候都应该只 selected 而所有其他的都应该不 selected。
发生了什么事,我怎样才能将新添加的节点包含到 jQuery selectors 中?
$(function() {
//check first box
$("input.duty:first").prop("checked", true);
//clicking unchecked box should check that box
//unchecks all others
$(".duty").on('click', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});
$("#addCasePoint").on("click", function() {
var newRowIndex = $('#newRowIndex').text();
var template = $('#casePointTemplate').data('template');
template = template.replace(/__index__/g, newRowIndex);
$('#casePointsFieldset').append(template);
$('#newRowIndex').text(++newRowIndex);
return false;
});
//deletes case point
$("#selection").on("click", ".removeCase", function() {
var caseCount = $('#selection .casePointFieldset').length
if (caseCount === 1) return false; //keep at least one row
$(this).closest("fieldset").remove();
return false;
});
});
.casePointFieldset {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="selection">
<fieldset id="casePointsFieldset">
<legend>Case Points</legend>
<div id="pointFieldset">
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
</div>
<!-- include template -->
<span id="casePointTemplate" data-template="<fieldset class="casePointFieldset"><div><label><span>Duty:</span> <input name="point[__index__]" class="duty" value="1" type="checkbox"></label></div><button class="removeCase">Remove</button></fieldset>">
</span>
</fieldset>
<button id="addCasePoint">Add Point</button>
</form>
最简单的方法是将事件附加到文档中。过去这是使用 live()
方法完成的。
$(document).on('click', '.duty', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});
问题在于您如何绑定它们。 .click
函数(或 .on('click')
)基本上是这样工作的:
- 查找与选择器 (
$('.your.selector.here')
) 匹配的所有 当前存在的 元素
- 将事件处理程序附加到每个 那些 元素
注意到我是如何提到它绑定到已经存在的吗?这意味着它不会自动绑定到新创建的。但是,您可以使用 .on
绑定到这些元素的父元素,然后监听选择器上的事件。我会告诉你我的意思:
$('#addItem').click(function() {
$('.container').append('<button class="item">Item</button>');
});
// Notice that I'm binding to the parent
// then specifying which events from it's children
// I want to listen to (click events from .item elements)
$('.container').on('click', '.item', function() {
console.log("I'm an item");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button class="item">Item</button>
</div>
<button id="addItem">Add New Item</button>
如果您将 on('click'
更改为那样工作,那么您将没有任何问题。
TL;DR:
我使用 $(..).append(node)
,但不考虑包含新添加的节点,尽管它们(假定)匹配 jQuery select 或
问题
我在下面有一些代码使用复选框但模拟单选按钮的行为。换句话说,任何时候都只能(有效地)select 编辑一个复选框。不应超过一个 selected。
如果您 运行 下面的示例并单击前 3 个复选框,它们将像单选按钮一样工作。无论您点击多少,都只会 selected。
但是,如果你添加点,新添加的点将不会被JS考虑,即使理论上它也应该抓住它们...
具体来说:您可以select新添加的复选框,它将select添加到已经select的复选框中之前。这是不正确的,因为任何时候都应该只 selected 而所有其他的都应该不 selected。
发生了什么事,我怎样才能将新添加的节点包含到 jQuery selectors 中?
$(function() {
//check first box
$("input.duty:first").prop("checked", true);
//clicking unchecked box should check that box
//unchecks all others
$(".duty").on('click', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});
$("#addCasePoint").on("click", function() {
var newRowIndex = $('#newRowIndex').text();
var template = $('#casePointTemplate').data('template');
template = template.replace(/__index__/g, newRowIndex);
$('#casePointsFieldset').append(template);
$('#newRowIndex').text(++newRowIndex);
return false;
});
//deletes case point
$("#selection").on("click", ".removeCase", function() {
var caseCount = $('#selection .casePointFieldset').length
if (caseCount === 1) return false; //keep at least one row
$(this).closest("fieldset").remove();
return false;
});
});
.casePointFieldset {
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="selection">
<fieldset id="casePointsFieldset">
<legend>Case Points</legend>
<div id="pointFieldset">
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
<fieldset class="casePointFieldset">
<div>
<label><span>Duty:</span> <input name="point[1]" class="duty" value="1" type="checkbox"></label>
</div>
<button class="removeCase">Remove</button>
</fieldset>
</div>
<!-- include template -->
<span id="casePointTemplate" data-template="<fieldset class="casePointFieldset"><div><label><span>Duty:</span> <input name="point[__index__]" class="duty" value="1" type="checkbox"></label></div><button class="removeCase">Remove</button></fieldset>">
</span>
</fieldset>
<button id="addCasePoint">Add Point</button>
</form>
最简单的方法是将事件附加到文档中。过去这是使用 live()
方法完成的。
$(document).on('click', '.duty', function(event) {
$("input.duty").prop("checked", false);
$(this).prop("checked", true);
});
问题在于您如何绑定它们。 .click
函数(或 .on('click')
)基本上是这样工作的:
- 查找与选择器 (
$('.your.selector.here')
) 匹配的所有 当前存在的 元素
- 将事件处理程序附加到每个 那些 元素
注意到我是如何提到它绑定到已经存在的吗?这意味着它不会自动绑定到新创建的。但是,您可以使用 .on
绑定到这些元素的父元素,然后监听选择器上的事件。我会告诉你我的意思:
$('#addItem').click(function() {
$('.container').append('<button class="item">Item</button>');
});
// Notice that I'm binding to the parent
// then specifying which events from it's children
// I want to listen to (click events from .item elements)
$('.container').on('click', '.item', function() {
console.log("I'm an item");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<button class="item">Item</button>
</div>
<button id="addItem">Add New Item</button>
如果您将 on('click'
更改为那样工作,那么您将没有任何问题。