更好的方法是委托事件,这意味着在它冒泡到父节点时捕获它。
委托 - 概述
该解决方案更加稳健和高效。
即使稍后将更多行动态添加到表中,它也允许处理事件,并且还会导致将单个事件处理程序附加到父节点(table
元素),而不是为每个子节点(tr
元素)附加一个事件处理程序。
假设 OP 的例子是一个简化的例子,表的结构可以更复杂,例如:
<table id="indexedTable">
...
<tr>
<td><p>1</p></td>
<td>2</td>
<td><p>3</p></td>
</tr>
</table>
因此,像获取这样的简单方法是e.target.parentElement
行不通的,因为单击内部<p>
和单击中心<td>
会产生不同的结果。
使用委托规范了事件处理,仅假设没有嵌套表。
执行
以下两个片段是等效的:
$("#indexedTable").delegate("tr", "click", function(e) {
console.log($(e.currentTarget).index() + 1);
});
$("#indexedTable").on("click", "tr", function(e) {
console.log($(e.currentTarget).index() + 1);
});
它们将侦听器附加到table
元素并处理从表行中冒泡的任何事件。当前 API 是on
方法,delegate
方法是遗留 API(实际上on
是在幕后调用)。
请注意,两个函数的参数顺序不同。
例子
下面或在 jsFiddle 上提供了直接处理程序附件和委托之间的比较:
$("#table-delegate").on("click", "tr", function(e) {
var idx = $(e.currentTarget).index() + 1;
$("#delegation-idx").text(idx);
console.log('delegated', idx);
});
$("#table-direct tr").on("click", function(e) {
var idx = $(e.currentTarget).index() + 1;
$("#direct-idx").text(idx);
console.log('direct', idx);
});
$('[data-action=add-row]').click(function(e) {
var id = e.target.dataset.table;
$('#' + id + ' tbody')
.append($('<tr><td>extra</td><td>extra</td><td>extra</td></tr>')[0])
});
tr:hover{
background:#ddd;
}
button.add-row {
margin-bottom: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<h1>Event handling test</h1>
<p>Add rows to both tables and see the difference in handling.</p>
<p>Event delegation attaches a single event listener and events related to newly added children are caught.</p>
<p>Direct event handling attaches an event handler to each child, where children added after the inital handler attachment don't have a handler attached to them, and therefore their indices won't be logged to console.</p>
<h2>Delegation</h2>
<p><span>row index: </span><span id="delegation-idx">unknown</span></p>
<button class="add-row" data-action="add-row" data-table="table-delegate">Add row to delegation</button>
<table id="table-delegate" class="table">
<tbody>
<tr>
<td>normal</td>
<td>normal</td>
<td>normal</td>
</tr>
<tr>
<td><p>nested</p></td>
<td><p>nested</p></td>
<td><p>nested</p></td>
</tr>
<tr>
<td>normal</td>
<td>normal</td>
<td><p>nested</p></td>
</tr>
</table>
<h2>Direct attachment</h2>
<p><span>row index: </span><span id="direct-idx">unknown</span></p>
<button class="add-row" data-action="add-row" data-table="table-direct">Add row to direct</button>
<table id="table-direct" class="table">
<tbody>
<tr>
<td>normal</td>
<td>normal</td>
<td>normal</td>
</tr>
<tr>
<td><p>nested</p></td>
<td><p>nested</p></td>
<td><p>nested</p></td>
</tr>
<tr>
<td>normal</td>
<td>normal</td>
<td><p>nested</p></td>
</tr>
</tbody>
</table>
这是jsFiddle上的演示。
PS:
如果您确实有嵌套表(或者,在一般情况下,希望委托给具有特定深度的元素),您可以使用jQuery 错误报告中的这个建议。