效果
效果图知识点
- input[type="checkbox"]
- checked
- Event
- shiftKey
笔记
本例需要实现通过按住 shift 键,可以批量选中复选框。
本例的难点是如何判断两个被选中 input 元素之间的范围,只要解决了这个,本例就不难了。
Wes Bos 的思路是通过声明一个变量,这个变量只有两个值:true
或 false
,初始值设为 false,我们把它当做一个开关,如果当这个开关处于 true
状态时, input 元素都应该为 checked
(选中)状态。
我们先获取所有的 input 元素:
const checkboxes = document.querySelectorAll('.inbox input[type="checkbox"]')
let lastChecked
同时声明一个变量 lastChecked 用来记录最后点击的那个 input 元素。
此时可以给所有 input 元素添加事件监听,我们同时创建一个函数 handleCheck 用来处理这些事件:
function handleCheck(e) {
let inBetween = false
lastChecked = this
}
checkboxes.forEach(checkbox => checkbox.addEventListener('click', handleCheck))
这里的变量 inBetween 就是我们前面提到的那个开关。
此时,完善函数,使其判断只有在 shift 键按下且 input 处于选中状态时,才开启开关 inBetween:
function handleCheck(e) {
let inBetween = false
if (e.shiftKey && this.checked) {
inBetween = true
}
lastChecked = this
}
此时我们可以通过 forEach 遍历,来改变其他 input 元素的状态:
function handleCheck(e) {
let inBetween = false
if (e.shiftKey && this.checked) {
checkboxes.forEach(checkbox => {
inBetween = true
if (inBetween) {
checkbox.checked = true
}
})
}
lastChecked = this
}
现在,我们运行一下,看看效果……
你会发现,我们并没有实现要求,不该选的 input 也全都选中了,这是为什么呢?
forEach() 方法遍历,会从头到尾把所有能遍历的元素都遍历一遍,这样一来,其实从头到尾,inBetween 这个开关一直是开着的,我们需要增加一个判断,使其在不需要时关闭,需要时打开。我们继续改写函数:
function handleCheck(e) {
let inBetween = false
if (e.shiftKey && this.checked) {
checkboxes.forEach(checkbox => {
// inBetween = true 删除这一句!
if (checkbox === this || checkbox === lastChecked) {
inBetween = !inBetween
}
if (inBetween) {
checkbox.checked = true
}
})
}
lastChecked = this
}
如上:我们判断只有当循环遇到 lastChecked 或者当前点击的那个 input 时,inBetween 状态进行反转。这时我们在运行程序看看,OK,大功告成!
网友评论