随机颜色生成器点击监听器e.stopPropagation不生效问题求助
随机颜色生成器事件冲突问题及解决方案
问题描述
我正在开发一个随机颜色生成器,每生成一个颜色就会创建对应的色块,你可以将鼠标悬浮在任意色块上,复制或者锁定你喜欢的颜色。
现在遇到的问题是:我点击复制按钮或者色块背景区域时,会同时触发锁定按钮的点击事件,点击锁定按钮时也会触发复制按钮的事件。
我不清楚问题出在哪里,因为相关处理函数中已经添加了e.stopPropagation()代码。
效果示意图:
我是JavaScript新手,如果你发现代码中有可以优化的地方,麻烦告知我优化方案,非常感谢。
问题根源
你遇到的事件同时触发的问题和e.stopPropagation()无关,这个API的作用是阻止事件冒泡到父级DOM节点,而你是给同一个色块元素同时绑定了两个click事件监听器,同一元素上的同类型事件会按绑定顺序依次触发,stopPropagation无法阻止这类同元素多监听函数的执行。
修复方案
将点击事件绑定到你动态生成的copy、lock两个span元素上,而不是绑定到父级色块,即可避免事件冲突:
// 修改后的hover2核心逻辑示例 function hover2() { const copyText = document.createElement('span'); const lockText = document.createElement('span'); copyText.textContent = "copy"; copyText.classList.add("hoverText"); lockText.classList.add("hoverText"); lockText.textContent = this.hasAttribute('locked') ? "locked" : "lock"; this.classList.add('box-animation'); this.removeEventListener('mouseover', hover2); changeBackgroundColor(this.style.backgroundColor); // 给copy按钮单独绑定事件 copyText.addEventListener('click', (e) => { e.stopPropagation(); navigator.clipboard.writeText(this.style.backgroundColor); copyText.textContent = "copied"; }) // 给lock按钮单独绑定事件 lockText.addEventListener('click', (e) => { e.stopPropagation(); if (!this.hasAttribute('locked')) { this.setAttribute('locked', 'true'); lockText.textContent = "locked"; } else { this.removeAttribute('locked'); lockText.textContent = "lock"; } }) function leaving() { copyText.remove(); lockText.remove(); this.classList.remove('box-animation'); this.addEventListener('mouseover', hover2); this.removeEventListener('mouseleave', leaving); } this.addEventListener('mouseleave', leaving) this.append(lockText, copyText); }
其他代码优化建议
- 目前你每次hover色块都会重新创建DOM、绑定事件,hover结束又销毁,开销较大。建议创建色块时就生成copy、lock元素默认隐藏,hover时仅切换显示状态,避免重复操作DOM。
- 全局空格按键事件需要增加
e.preventDefault()逻辑,否则按空格会触发页面滚动的默认行为。 - 生成带透明度的颜色时,语法应该使用
rgba而非rgb,你当前返回的rgb(${r},${g},${b},${alpha})属于不规范写法,部分浏览器可能解析异常,修改为rgba(${r},${g},${b},${alpha})兼容性更好。 - 筛选未锁定色块时,可以直接用
[...colorContainer.children].filter(box => !box.hasAttribute("locked")),无需调用Object.values转换。
内容的提问来源于stack exchange,提问作者Kosciasty
相关产品推荐
相关产品推荐

