复选框必须置于或内,不可直接放在中;表头全选框放,行内复选框须为直接子元素,且用不同name区分逻辑分组,全选框监听change事件并手动维护indeterminate状态。

复选框必须放在 里,不能塞进
或
浏览器会直接丢弃写在
内部但没包裹在 或
中的 <input type="checkbox">。常见错误写法:<tr>
<input type="checkbox"><td>张三</td>
</tr>——这个复选框根本不会渲染出来。正确做法是为控制列单独设一列,每行一个 <td>,里面只放复选框:<pre class="brush:php;toolbar:false;"><thead><tr>
<th><input type="checkbox" id="check-all"></th>
<th>姓名</th>
<th>邮箱</th>
</tr></thead><tbody><tr>
<td><input type="checkbox" name="item" value="1001"></td>
<td>张三</td>
<td>zhang@example.com</td>
</tr></tbody></pre>
<p>表头复选框可以放在 <code><th> 里,但行内复选框必须是 <code><td> 的直接子元素。<h3>全选框和行复选框要用 name 区分逻辑分组</h3>
<p>所有待控制的数据行复选框统一设 <code>name="item"(或其他业务名),表头全选框不设 name,或设为不同值(如 name="select-all")。这样能避免 JS 批量操作时误伤、后端接收时混淆。
常见错误:所有复选框都写 name="selected",结果 document.querySelectorAll('input[name="selected"]') 把全选框自己也拉进来了,导致“全选→取消→再全选”状态错乱。
-
document.querySelectorAll('input[name="item"]') 精准获取数据行复选框,排除全选框
- 表单提交时,
request.form.getlist("item") 能原生拿到选中 value 数组
- 不要用 class 或 data-* 属性做批量选择依据——动态渲染或 class 冲突时容易失效
全选框必须监听 change 事件,不是 click
click 在 Safari/iOS Webview 下点击 <label></label> 可能不触发;空格键聚焦切换时也不响应。change 是唯一能覆盖所有触发方式(鼠标、键盘、JS 调用)的语义化事件。
绑定示例:
document.getElementById('check-all').addEventListener('change', e => {
const boxes = document.querySelectorAll('input[name="item"]');
boxes.forEach(box => {
if (!box.disabled) box.checked = e.target.checked;
});
});
注意:e.target.checked 是当前真实状态;getAttribute('checked') 返回的是初始 HTML 属性,不可靠。
indeterminate 状态要手动维护,且必须先清空再设置
浏览器不会自动推断 “部分选中”,indeterminate 是纯视觉态,必须由 JS 主动设置,且它不影响 checked 值。
每次任意行复选框变化后,都要重新统计:
const boxes = document.querySelectorAll('input[name="item"]');
const checked = Array.from(boxes).filter(cb => cb.checked && !cb.disabled).length;
const total = Array.from(boxes).filter(cb => !cb.disabled).length;
<p>const checkAll = document.getElementById('check-all');
checkAll.indeterminate = false; // 先清掉旧状态
if (checked === 0) {
checkAll.checked = false;
} else if (checked === total) {
checkAll.checked = true;
} else {
checkAll.checked = false;
checkAll.indeterminate = true;
}</p>
漏掉 indeterminate = false 这一步,旧状态会残留,UI 就卡在横杠上不动。
真正麻烦的不是写几行 JS,而是每行复选框的 value 必须是后端可识别的唯一 ID,否则批量操作时收不到数据或收错。
浏览器会直接丢弃写在
<input type="checkbox">。常见错误写法:<tr>
<input type="checkbox"><td>张三</td>
</tr>——这个复选框根本不会渲染出来。正确做法是为控制列单独设一列,每行一个 <td>,里面只放复选框:<pre class="brush:php;toolbar:false;"><thead><tr>
<th><input type="checkbox" id="check-all"></th>
<th>姓名</th>
<th>邮箱</th>
</tr></thead><tbody><tr>
<td><input type="checkbox" name="item" value="1001"></td>
<td>张三</td>
<td>zhang@example.com</td>
</tr></tbody></pre>
<p>表头复选框可以放在 <code><th> 里,但行内复选框必须是 <code><td> 的直接子元素。<h3>全选框和行复选框要用 name 区分逻辑分组</h3>
<p>所有待控制的数据行复选框统一设 <code>name="item"(或其他业务名),表头全选框不设 name,或设为不同值(如 name="select-all")。这样能避免 JS 批量操作时误伤、后端接收时混淆。
常见错误:所有复选框都写 name="selected",结果 document.querySelectorAll('input[name="selected"]') 把全选框自己也拉进来了,导致“全选→取消→再全选”状态错乱。
-
document.querySelectorAll('input[name="item"]')精准获取数据行复选框,排除全选框 - 表单提交时,
request.form.getlist("item")能原生拿到选中 value 数组 - 不要用 class 或 data-* 属性做批量选择依据——动态渲染或 class 冲突时容易失效
全选框必须监听 change 事件,不是 click
click 在 Safari/iOS Webview 下点击 <label></label> 可能不触发;空格键聚焦切换时也不响应。change 是唯一能覆盖所有触发方式(鼠标、键盘、JS 调用)的语义化事件。
绑定示例:
document.getElementById('check-all').addEventListener('change', e => {
const boxes = document.querySelectorAll('input[name="item"]');
boxes.forEach(box => {
if (!box.disabled) box.checked = e.target.checked;
});
});
注意:e.target.checked 是当前真实状态;getAttribute('checked') 返回的是初始 HTML 属性,不可靠。
indeterminate 状态要手动维护,且必须先清空再设置
浏览器不会自动推断 “部分选中”,indeterminate 是纯视觉态,必须由 JS 主动设置,且它不影响 checked 值。
每次任意行复选框变化后,都要重新统计:
const boxes = document.querySelectorAll('input[name="item"]');
const checked = Array.from(boxes).filter(cb => cb.checked && !cb.disabled).length;
const total = Array.from(boxes).filter(cb => !cb.disabled).length;
<p>const checkAll = document.getElementById('check-all');
checkAll.indeterminate = false; // 先清掉旧状态
if (checked === 0) {
checkAll.checked = false;
} else if (checked === total) {
checkAll.checked = true;
} else {
checkAll.checked = false;
checkAll.indeterminate = true;
}</p>
漏掉 indeterminate = false 这一步,旧状态会残留,UI 就卡在横杠上不动。
真正麻烦的不是写几行 JS,而是每行复选框的 value 必须是后端可识别的唯一 ID,否则批量操作时收不到数据或收错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











