[英]Event.target alternatives
我尝试使侧面导航在单击某处时关闭,但导航块本身及其切换按钮。 我尝试这样的代码:
的HTML
<div class="header__menu-toggle">
<div class="icon-menu"></div>
</div>
<section id="main-nav">
<ul class="main-nav__inner">
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
</section>
原生JS
var body = document.getElementsByTagName("body")[0];
var nav = document.getElementById('main-nav');
var navToggle = document.getElementsByClassName('header__menu-toggle')[0];
function closeAll(e) {
if (e.target != nav && e.target != navToggle) {
nav.classList.remove("main-nav--open");
}
}
body.addEventListener('click', closeAll)
问题在于e.target
等于点击的确切目标,而不是整个区块。 对于前。 单击<div class="icon-menu"></div>
不相等,请单击其父<div class="header__menu-toggle">
。 或单击导航块深处的子li
元素并不等于单击<section id="main-nav">
。 如何解决这个问题呢? 如何检查我是否共同单击导航块或navToggle块?
尝试:$(event.currentTarget)我认为这是解决方案,如果不尝试显示事件对象并找到事件的一些子属性,可以帮助您,此链接可以帮助event.currentTarget
我想类似的事情可能会起作用。
旁注: querySelector
和querySelectorAll
很棒,请改用它们。
var body = document.querySelector("body"); var nav = document.querySelector('#main-nav'); var navToggle = document.querySelector('.header__menu-toggle'); var nodeArr = [].slice.call(nav.childNodes); function closeAll(e) { if (nodeArr.indexOf(e.target) !== -1) { console.log('closing the nav') nav.classList.remove("main-nav--open"); } else { console.log('clicked inside nav') } } body.addEventListener('click', closeAll)
<div class="header__menu-toggle"> <div class="icon-menu"></div> </div> <section id="main-nav"> <ul class="main-nav__inner"> <li>one</li> <li>two</li> <li>three</li> </ul> </section>
为什么有效?
nav.childNodes
存储有关nav元素的所有子级的信息。 为了方便起见,我们将其转换为数组。 检测到click
后,我们检查点击目标是否属于导航(在阵列中)。
尝试从目标元素进入DOM树。
//function search for "search" element for "current" element and all his parents function isInside(search,current){ if (current!=search){ if (typeof current.parentNode != 'undefined' && current.parentNode!=null) return isInside(search,current.parentNode);//go to parent else return false;//our tree is over - this is outside element }else{ //yes this is element we looking for return true; } }; var search=document.querySelector("#container"); //usage document.querySelector("body").addEventListener("click",function(e){ if (isInside(search,e.target)){ console.log("click inside #container"); }else{ console.log("click outside #container"); } });
<html> <body> <div> This is wrong div</div> <div id="container" width="100px" height="100px" style="display:block; background:red"><ul><li><span>Test node</span></li></ul> </div> <div> This is wrong div</div> </body> </html>
说明-我从e.target节点开始,然后到结尾-如果找到与搜索元素匹配的父对象,则是一个结局-这意味着我们在其中,或者是这个元素,或者第二个结局是在树的末端-我们在外面。
可以通过添加例如我们应该提高多少级别来改进此方法。
在当前问题中, isInside函数的用法如下:
function closeAll(e) {
if (!isInside(nav,e.target) && !isInside(navToggle,e.target) ) {
nav.classList.remove("main-nav--open");
}
}
您可以使用jQuery方法“最近”
$(document).click( function(event){
if( $(event.target).closest("#main-nav").length ||
$(event.target).closest(".header__menu-toggle").length) return;
$("#main-nav").removeClass("main-nav--open");
}
event.path返回树结构的数组,可用于查找目标元素的父级。
用以下代码替换js代码:
var body = document.getElementsByTagName("body")[0];
var nav = document.getElementById('main-nav');
var navToggle = document.getElementsByClassName('header__menu-toggle')[0];
function closeAll(event) {
if (event.path.indexOf(nav) > -1 && event.path.indexOf(navToggle) > -1) {
nav.classList.remove("main-nav--open");
}
}
body.addEventListener('click', closeAll)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.