實現一個多級分類樹形結構的 父子級聯選中:
<ul><li> 結構。<ul class="categories">
<li><input type="checkbox" />數碼電子
<ul>
<li><input type="checkbox" />手機</li>
<li><input type="checkbox" />電腦</li>
</ul>
</li>
<li><input type="checkbox" />服裝
<ul>...</ul>
</li>
</ul>
關鍵:input 與子 ul 為**同層相鄰元素**,.next() 可精準獲取子列表。
$("ul.categories input").click(function() {
// 1. 獲取當前點擊 checkbox 的「直接子列表 ul」
var children = $(this).next();
// 2. 當前 checkbox 狀態
var isChecked = $(this).prop("checked");
// 3. 向下級聯:操作所有子孫 checkbox
if (children.length) {
if (isChecked) {
children.find("input").prop("checked", true); // 全選
} else {
children.find("input").prop("checked", false); // 全取消
}
}
// 4. 向上級聯:檢查「同級組」是否全選,決定父 checkbox 狀態
var $parentUl = $(this).parent().parent(); // 最近的祖先 ul
var checkedCount = $parentUl.find("> li > input:checked").length; // 同級被選數
var totalCount = $parentUl.find("> li > input").length; // 同級總數
var $parentCheckbox = $parentUl.parent().find("> input"); // 父 li 的直接 checkbox
if (checkedCount === totalCount) {
$parentCheckbox.prop("checked", true); // 同級全選 → 父選中
} else {
$parentCheckbox.prop("checked", false); // 否則父取消
}
});
<li> <-- $(this).parent().parent().parent()
<input> (父) <-- $parentCheckbox
<ul> <-- $parentUl
<li> <-- $(this).parent()
<input> (當前點擊) <-- $(this)
<ul> <-- children = $(this).next()
<li><input>...</li> <-- children.find("input")
</li>
</ul>
</li>
| 問題 | 原因 | 修正 |
|---|---|---|
| removeProp("checked") 報錯 | jQuery 1.6+ removeProp 刪除屬性導致無法再勾選 | 統一用 .prop("checked", false) |
| 多次點擊觸發重複遞歸 | 父 checkbox 變化又觸發 click 事件 | 用 change 事件 + 判斷 event.originalEvent 區分用戶/代碼觸發 |
| 動態添加節點無效 | 事件綁定在現有元素 | 用事件委託 $(document).on('change', 'ul.categories input', fn) |
{id, label, checked, children: []}。setChecked(node, val) 處理向下,updateParent(node) 向上冒泡計算。這段 jQuery 代碼利用 .next()、.parent()、.find() 精準操作 DOM 樹,實現了雙向級聯。理解「同層相鄰」與「祖先後代」關係是閱讀此類代碼的關鍵。實際項目建議遷移至數據驅動框架。