为何我的jQuery选择器无法实现点击非指定元素触发事件?
需求:点击网页上除带有navbutton类的菜单按钮外的任意元素时触发动作,但现有jQuery代码点击.navbutton时仍会弹出alert。
相关代码
HTML
<div class="test"> <nav id="menu" class="pdng-lr"> <div class="navbutton"> <span class="top"></span> <span class="middle"></span> <span class="bottom"></span> </div> </nav> </div>
CSS
#menu .navbutton { display:none; } @media screen and (max-device-aspect-ratio: 1/1) and (orientation: portrait) { .pdng-lr { padding:0px; } #menu .navbutton { display:block; width:25px; height:38px; margin-top:40px; margin-left:calc(100% - 40px); border:none; cursor:pointer; } #menu .navbutton span { display:inline-block; float:left; min-height:6px; width:100%; margin:2px 0px; background-color:#cccccc; -webkit-transition:all 0.15s linear; -moz-transition:all 0.15s linear; -o-transition:all 0.15s linear; transition:all 0.15s linear; } #menu .navbutton .top { margin-top:6px; } }
原jQuery代码
jQuery('div:not(".navbutton")').click(function(){ // 测试是否生效 alert(); });
问题原因
- 选择器逻辑错误:
div:not(".navbutton")选中的是所有不属于.navbutton类的div元素,但.navbutton本身是div,它的父级元素(#menu、.test)也都是div。点击.navbutton时,事件会向上冒泡到父级div,触发父级的点击回调,所以alert依然弹出。 - 未处理事件冒泡:即使选择器正确,事件冒泡机制也会让父元素的点击事件被触发,导致需求失效。
修复方案
方案一:事件委托+目标判断
给document绑定点击事件,通过判断点击目标是否属于.navbutton区域来决定是否执行动作:
jQuery(document).click(function(e) { // 检查点击目标及其父元素中是否包含.navbutton if (!jQuery(e.target).closest('.navbutton').length) { alert('触发动作'); } });
- 优势:无需给多个元素绑定事件,性能更优,且能处理动态生成的
.navbutton元素。
方案二:阻止.navbutton的事件冒泡
保留全局点击逻辑,同时给.navbutton绑定点击事件并阻止冒泡:
// 全局点击事件(绑定到body或document均可) jQuery('body').click(function() { alert('触发动作'); }); // 阻止.navbutton的事件向上冒泡 jQuery('.navbutton').click(function(e) { e.stopPropagation(); });
- 原理:
e.stopPropagation()会终止事件的冒泡过程,点击.navbutton时,父级元素的点击事件不会被触发。
内容的提问来源于stack exchange,提问作者fafa
相关产品推荐
相关产品推荐

