表格行 <tr> 或單元格 <td> 綁定點擊事件(如選中行、跳轉詳情),內部 <input type="checkbox"> 也綁定點擊事件(如批量操作選中)。點擊 Checkbox 時,**兩個事件同時觸發**,導致頁面跳轉或重複選中邏輯錯亂。
DOM 事件流三階段:捕獲 → 目標 → 冒泡。默認情況下,事件在目標元素觸發後,會**沿 DOM 樹向上冒泡**,依次觸發祖先元素的同類事件監聽器。
Checkbox 點擊 → 觸發 Checkbox click → 冒泡到 TD → 觸發 TD click → 冒泡到 TR → ...
// 原生 JS
document.querySelectorAll('td input[type="checkbox"]').forEach(cb => {
cb.addEventListener('click', e => e.stopPropagation());
});
// jQuery
$('td input[type="checkbox"]').on('click', e => e.stopPropagation());
優點:不影響其他交互,代碼極少。缺點:若父級使用事件委託(delegate/on),需確保選擇器精準匹配 Checkbox。
$('#table').on('click', 'td', function(e) {
if ($(e.target).is('input[type="checkbox"]')) return; // 忽略 checkbox 點擊
// 正常行點擊邏輯
});
優點:集中管理,適合動態生成的表格(事件委託)。缺點:若 TD 內還有其他可交互元素(<a>、<button>),需逐個排除。
td > input[type="checkbox"] { pointer-events: none; }
缺點:Checkbox 本身無法接收任何滑鼠事件(無法勾選、無法聚焦),**極不推薦**用於表單元素。
若需在冒泡前處理,可在父級添加捕獲監聽器:
document.getElementById('table').addEventListener('click', e => {
if (e.target.matches('input[type="checkbox"]')) {
e.stopImmediatePropagation(); // 連同同元素其他監聽器一起阻止
}
}, true); // true = 捕獲階段
<table> 或 <tbody>),動態行無需重綁。onclick 內聯屬性,污染全局作用域且難維護。@click.stop / @click.selfe.stopPropagation()(合成事件同樣支持)(click)="onRowClick($event)" 內部判斷 $event.target掌握事件流三階段,精準控制冒泡,是前端交互無 Bug 的基石。