取消勾选「保存颜色」复选框后页面立即变色的问题排查
解决取消「保存颜色」后页面立即变色的问题
你的问题出在点击「保存颜色」按钮的事件会冒泡到body元素:当取消勾选按钮时,togglePause()把paused状态切换为false,紧接着冒泡触发body上的点击事件,此时changeFn()里的暂停判断已经失效,所以直接执行了颜色切换。
下面是修复后的代码,同时还解决了原代码中事件移除无效的隐性问题:
class ColorVar { static instances = []; constructor(label, oCode) { this.label = label; this.oCode = oCode; ColorVar.instances.push(this); this.paused = false; // 跟踪暂停状态 } changeFn() { if (this.paused) return; const rVal = () => Math.floor(Math.random() * 255); const clrCode = `rgb(${rVal()}, ${rVal()}, ${rVal()})`; document.body.style.setProperty(this.label, clrCode); } cResetFn() { document.body.style.setProperty(this.label, this.oCode); } togglePause() { this.paused = !this.paused; } } const color1 = new ColorVar("--color1", "#b4e8b4"); const color2 = new ColorVar("--color2", "#1f1f7c"); const color3 = new ColorVar("--color5", "#fc8eac"); const colorSwitch = document.getElementById('colorSwitch'); const pauseButton = document.getElementById('pauseButton'); const pauseLabel = document.getElementById('pauseLabel'); // 抽离body点击处理函数,确保绑定/移除的是同一个引用 const handleBodyClick = () => { ColorVar.instances.forEach(colorVar => colorVar.changeFn()); }; colorSwitch.addEventListener('change', () => { if (colorSwitch.checked) { pauseLabel.classList.remove('hidden'); pauseButton.classList.remove('hidden'); document.body.addEventListener('click', handleBodyClick); } else { ColorVar.instances.forEach(colorVar => colorVar.cResetFn()); document.body.removeEventListener('click', handleBodyClick); pauseLabel.classList.add('hidden'); pauseButton.classList.add('hidden'); // 重置所有实例的暂停状态 ColorVar.instances.forEach(colorVar => colorVar.paused = false); } }); pauseButton.addEventListener('click', (event) => { // 阻止事件冒泡到body,避免触发颜色切换 event.stopPropagation(); ColorVar.instances.forEach(colorVar => colorVar.togglePause()); });
关键修改点说明:
- 阻止事件冒泡:在
pauseButton的点击事件中加入event.stopPropagation(),点击按钮时不会触发body上的点击逻辑,切换暂停状态时就不会意外变色。 - 统一事件处理函数引用:把body的点击逻辑抽成
handleBodyClick变量,原代码中用匿名函数绑定/移除,实际上每次都是新函数,导致移除操作无效,现在可以正确移除事件监听。 - 优化开关逻辑:去掉原代码中
!pauseButton.checked的判断,只要开启换色开关就显示暂停按钮,避免逻辑冲突;同时关闭开关时重置所有实例的暂停状态,保持功能一致性。
内容的提问来源于stack exchange,提问作者Sam williams
相关产品推荐
相关产品推荐

