效果
要点
首获取到的 <input>
组转化为数组,针对每次操作,获取 A 和 B,利用 indexOf()
来获得 A 和 B 在数组中的索引值,由此即可确定范围,并能通过 slice()
来直接截取 A-B 的所有 DOM 元素,并进行状态改变的操作,而变量 onOff
表示 A-B 范围内的状态,true
表示选中,false
表示取消选中。
-
转换 Nodelist 为数组
const boxs = document.querySelectorAll('.inbox input[type="checkbox"]'); const boxArr = Array.from(boxs);
-
针对按下了 Shift 键的情况,获取 A-B 范围
let start = boxArr.indexOf(this); let end = boxArr.indexOf(lastChecked);
-
截取该范围内的数组元素,并改变选中状态
boxArr.slice(Math.min(start, end), Math.max(start, end) + 1) .forEach(input => input.checked = onOff);
-
确定选中 or 取消选中
onOff = lastChecked.checked ? true : false;
-
标记 A 值
if(!lastChecked) lastChecked = this; /* ... */ lastChecked = this;
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<style>
html {
font-family: sans-serif;
background: #09b8af;
}
.inbox {
max-width: 400px;
margin: 50px auto;
background: white;
border-radius: 5px;
box-shadow: 10px 10px 0 rgba(0, 0, 0, 0.1);
}
.item {
display: flex;
align-items: center;
border-bottom: 1px solid #F1F1F1;
}
.item:last-child {
border-bottom: 0;
}
input:checked+p {
background: #F9F9F9;
text-decoration: line-through;
}
input[type="checkbox"] {
margin: 20px;
}
p {
margin: 0;
padding: 20px;
transition: background 0.2s;
flex: 1;
font-family: 'helvetica neue';
font-size: 20px;
font-weight: 200;
border-left: 1px solid #D1E2FF;
}
.details {
text-align: center;
font-size: 15px;
}
</style>
<div class="inbox">
<div class="item">
<input type="checkbox">
<p> 推出的 30 天挑战</p>
</div>
<div class="item">
<input type="checkbox">
<p>项目免费提供了 30 个视频教程</p>
</div>
<div class="item">
<input type="checkbox">
<p>起始文档</p>
</div>
<div class="item">
<input type="checkbox">
<p>挑战解决方案源代码</p>
</div>
<div class="item">
<input type="checkbox">
<p>用纯 JavaScript 来写东西</p>
</div>
<div class="item">
<input type="checkbox">
<p>不借助框架和库</p>
</div>
<div class="item">
<input type="checkbox">
<p>也不使用编译器和引用</p>
</div>
<div class="item">
<input type="checkbox">
<p>JavaScript30 是 Wes Bos </p>
</div>
<div class="item">
<input type="checkbox">
<p>按住 Shift 的多选功能</p>
</div>
</div>
<script>
const boxs = document.querySelectorAll('.inbox input[type="checkbox"]');
boxs.forEach(box => box.addEventListener('click', handleCheck));
// 转换 Nodelist 为数组
const boxArr = Array.from(boxs);
let lastChecked;
// onOff 表示 A-B 范围内的状态,true 表示选中,false 表示取消选中
let onOff = false;
// 利用数组索引获取需要选中的范围
function handleCheck(e) {
if (!lastChecked) lastChecked = this;
onOff = lastChecked.checked ? true : false;
if (e.shiftKey) {// 按下 shift
// 用 indexOf()来获得 A 和 B 在数组中的索引值,由此即可确定范围
let start = boxArr.indexOf(this);
let end = boxArr.indexOf(lastChecked);
// 通过 slice()来直接截取 A-B 的所有 DOM 元素,并进行状态改变的操作
boxArr.slice(Math.min(start, end), Math.max(start, end) + 1)
.forEach(input => input.checked = onOff);
console.log(start + "+" + end);
}
lastChecked = this;
}
</script>
</body>
</html>