如何用JavaScript优雅处理弹窗点击事件(点击外部关闭)
问题
我通过JavaScript实现了点击按钮打开弹窗的功能,要求点击弹窗内部不会关闭弹窗,仅点击弹窗外部可关闭。目前我通过获取e.target.className来判断是否关闭弹窗,但弹窗内元素较多时这种方法并不合理,请问有没有规范的优化方案?
优化方案
方案1:通过阻止事件冒泡实现隔离
核心逻辑是让弹窗内部的点击事件不向上传递到document,只有外部点击才触发关闭:
- 给按钮点击事件添加
e.stopPropagation(),避免刚打开弹窗就触发document的关闭逻辑; - 给弹窗容器绑定点击事件,同样调用
e.stopPropagation(),阻止内部点击事件冒泡; document的点击事件只负责关闭弹窗,无需逐个判断元素类名。
方案2:用closest()判断点击区域
利用DOM方法closest()快速检测点击目标是否属于弹窗内部:
$(e.target).closest('.dialog')会返回弹窗容器(如果点击的是弹窗或其子元素),否则返回空;- 结合按钮本身的判断,确保点击按钮时不会误关闭弹窗。
修改后的代码
HTML(结构不变)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <button class="click">click <div class="dialog"> <header class="head"> <h1 class="title">my is title</h1> </header> <ul class='dialog_wrap'> <li class='item'> <p class='text'>Lorem ipsum dolor, sit amet consectetur</p> <span class='time'>2022-12-23</span> </li> <li class='item'> <p class='text'>Lorem ipsum dolor, sit amet consectetur</p> <span class='time'>2022-12-23</span> </li> <li class='item'> <p class='text'>Lorem ipsum dolor, sit amet consectetur</p> <span class='time'>2022-12-23</span> </li> <li class='item'> <p class='text'>Lorem ipsum dolor, sit amet consectetur</p> <span class='time'>2022-12-23</span> </li> <input type="button" value="confirm" class="confirm"> </ul> </div> </button>
CSS(保持原样式)
.click { position: relative; } .click .dialog { display: none; width: 300px; position: absolute; background-color: yellow; border: 1px solid #ccc; } .click .dialog li { text-align: left; } .click .dialog .confirm { margin-top: 20px; }
JavaScript(方案1实现)
// 按钮点击切换弹窗显示 $('.click').on('click', function(e) { e.stopPropagation(); $('.dialog').toggle(); }); // 阻止弹窗内部点击事件冒泡 $('.dialog').on('click', function(e) { e.stopPropagation(); }); // 点击外部关闭弹窗 $(document).on('click', function() { $('.dialog').hide(); });
JavaScript(方案2实现)
$('.click').on('click', function(e) { e.stopPropagation(); $('.dialog').toggle(); }); // 判断点击区域,仅外部点击关闭弹窗 $(document).on('click', function(e) { const isDialog = $(e.target).closest('.dialog').length; const isTriggerBtn = $(e.target).hasClass('click'); if (!isDialog && !isTriggerBtn) { $('.dialog').hide(); } });
内容的提问来源于stack exchange,提问作者AWEI
相关产品推荐
相关产品推荐

