效果图
不管三七二十一,一图走天下,如下:
应用场景
更好的用户体验,不需要精准的点击小小的CheckBox实现单选全选
html
<div class="table-box">
<table>
<thead>
<tr class="check-all">
<th>
<input type="checkbox">
</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
</tr>
</thead>
<tbody id="table"></tbody>
</table>
</div>
css
.table-box{width: 500px; height: 800px; margin: 200px auto;}
table {width: 100%; border-collapse: collapse;}
table td, table th{text-align: center; padding: 10px 0;}
tr:hover{background: lightblue; cursor: pointer;}
js
let table = $('#table');
for (let i = 0; i < 5; i++) { //循环插入tr
let tr = $('<tr></tr>');
tr.append('<td><input type="checkbox"></td>');
for (let j = 0; j < 4; j++) { //循环插入td
tr.append('<td>内容</td>')
}
table.append(tr);
}
$('.check-all').click(function() {
let checkall = $(this).find('input');
let checkBtn = $('#table').find('input');
if (checkall[0].checked) { //判断全选按钮的 checked 值,点击 tr 改变它的 checked
checkall.prop('checked', false);
} else {
checkall.prop('checked', true);
}
checkBtn.prop('checked', checkall[0].checked); //将单选按钮的 checked 值设为全选按钮的 checked 值
})
$('#table').on('click', 'tr', function() {
let inputChild = $(this).find('input');
let len = $(this).parents('#table').find('input').length; //按钮总长度
if (inputChild[0].checked) { //判断每一行按钮的 checked 值,点击该行改变它的 checked
inputChild.prop('checked', false);
} else {
inputChild.prop('checked', true);
}
let inputCheckAll = $(this).parents('#table').find('input:checked').length; //获取选中的按钮长度(ps:放在此处,确保获取的选中个数是对的)
if (inputCheckAll === len) { //判断 选中的按钮长度 是否等于 按钮总长度,选中全选按钮
$('.check-all').find('input').prop('checked', true);
} else {
$('.check-all').find('input').prop('checked', false);
}
console.log(inputCheckAll);
console.log(len);
})
结束
实现原理不做过多说明,js中注释写的很清晰。
2023-08-06:补充一个完善版
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.table-box {
width: 500px;
height: 800px;
margin: 20px auto;
user-select: none;
}
input {
width: 16px;
height: 16px;
}
table {
width: 100%;
border-collapse: collapse;
}
table td, table th {
text-align: center;
padding: 10px 0;
}
tr:hover {
background: lightblue;
cursor: pointer;
}
</style>
</head>
<body>
<div class="table-box">
<table>
<thead>
<tr class="check-all-row">
<th>
<input type="checkbox">
</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
<th>标题</th>
</tr>
</thead>
<tbody id="tbody"></tbody>
</table>
</div>
<script>
const $ = selector => document.querySelector(selector)
const $2 = selector => document.querySelectorAll(selector)
const tbody = $('#tbody')
// 全选行
const checkAll = $('.check-all-row')
// 全选行内的 input
const checkAllInput = checkAll.querySelector('input')
// 生成布局
Array.from({length: 5}).forEach(() => {
const tr = '<td><input type="checkbox"></td>' + '<td>内容</td>'.repeat(4)
tbody.insertAdjacentHTML('afterbegin', tr)
})
// 所有的单选行
const rows = [...$2('#tbody tr')]
const rowsSize = rows.length
// 所有单选行内的 input
const inputs = rows.map(tr => tr.querySelector('input'))
// 点击全选行的操作
function clickCheckAll() {
const checkedSize = inputs.filter(input => input.checked).length
checkAllInput.indeterminate = checkedSize && checkedSize !== rowsSize
checkAllInput.checked = checkedSize === rowsSize
}
function setInputsChecked(checked) {
inputs.forEach(input => input.checked = checked)
}
// 点击 全选行
checkAll.onclick = function ({target}) {
// 判断是否是 input 元素冒泡触发的事件
if (target.nodeName === 'INPUT') {
return setInputsChecked(target.checked)
}
const checked = !checkAllInput.checked
checkAllInput.checked = checked
setInputsChecked(checked)
}
rows.forEach(tr => {
// 点击单选行
tr.onclick = function ({target}) {
// 判断是否是 input 元素冒泡触发的事件
if (target.nodeName === 'INPUT') {
return clickCheckAll()
}
const input = this.querySelector('input')
input.checked = !input.checked
clickCheckAll()
}
})
</script>
</body>
</html>