不使用Event接口,如何避免点击子元素触发父元素onclick?
问题解决:仅触发子元素点击事件(不使用Event接口)
问题描述
- 核心需求:点击
<strong>包裹的文本时,仅改变该<strong>元素的颜色,不触发父级<p>元素的颜色切换;仅使用原生onclick属性,禁止使用Event接口、React或jQuery。 - 现有问题:当
<strong>是<p>的子元素时,点击<strong>会同时触发父<p>的onclick事件,导致两者颜色都发生变化。 - 当前实现代码:
selectElements.forEach(elem => { function change() { if (elem.style.color == 'red') { elem.style.color = 'blue'; } else { elem.style.color = 'red'; } } elem.onclick = change; });
可行解决方案
方案1:利用this匹配触发元素
修改代码,通过this判断当前实际触发事件的元素是否为绑定事件的元素本身,从而跳过父元素的执行逻辑:
selectElements.forEach(elem => { elem.onclick = function() { // 仅当实际点击的元素是当前绑定事件的元素时,才执行颜色切换 if (this !== elem) return; elem.style.color = elem.style.color === 'red' ? 'blue' : 'red'; }; });
原理:事件冒泡时,父<p>的onclick函数中,this指向的是实际被点击的<strong>元素,和elem(即<p>)不相等,因此直接返回,不执行颜色切换;而点击<p>的非子元素区域时,this等于elem,正常执行颜色切换逻辑。
方案2:通过全局标记阻止父元素执行
给子元素的点击处理添加全局标记,让父元素检测到标记后跳过执行:
selectElements.forEach(elem => { elem.onclick = function() { // 若已有子元素处理过点击,重置标记并返回 if (window.clickHandled) { window.clickHandled = false; return; } // 如果当前元素是STRONG,标记点击已被处理 if (elem.tagName === 'STRONG') { window.clickHandled = true; } elem.style.color = elem.style.color === 'red' ? 'blue' : 'red'; }; });
原理:点击<strong>时,先设置clickHandled为true;当事件冒泡到父<p>时,检测到该标记就直接返回,不执行父元素的颜色切换;最后重置标记,避免影响后续的点击操作。
内容的提问来源于stack exchange,提问作者Keith Rubin
相关产品推荐
相关产品推荐

