简体   繁体   English

Event.target替代方案

[英]Event.target alternatives

I try to make side navigation close on click somewhere but navigation block itself and its toggle button. 我尝试使侧面导航在单击某处时关闭,但导航块本身及其切换按钮。 I try such code: 我尝试这样的代码:

HTML 的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>

NATIVE JS 原生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)

The problem is that e.target equals to an exact target of click, not whole block. 问题在于e.target等于点击的确切目标,而不是整个区块。 For ex. 对于前。 click on <div class="icon-menu"></div> is not equal click on its parent <div class="header__menu-toggle"> . 单击<div class="icon-menu"></div>不相等,请单击其父<div class="header__menu-toggle"> Or click on child li elements deep in navigation block isn't equal to click on <section id="main-nav"> . 或单击导航块深处的子li元素并不等于单击<section id="main-nav"> How to solve this problem? 如何解决这个问题呢? How to check if I click on navigation block or navToggle block in common? 如何检查我是否共同单击导航块或navToggle块?

尝试:$(event.currentTarget)我认为这是解决方案,如果不尝试显示事件对象并找到事件的一些子属性,可以帮助您,此链接可以帮助event.currentTarget

I guess something like this may work. 我想类似的事情可能会起作用。

Side note: querySelector and querySelectorAll are great, use them instead. 旁注: querySelectorquerySelectorAll很棒,请改用它们。

 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> 

Why it works? 为什么有效?

nav.childNodes stores information about all children of the nav element. nav.childNodes存储有关nav元素的所有子级的信息。 We convert it to array for convenience. 为了方便起见,我们将其转换为数组。 After click is detected we check if the click target belongs to the nav (is in the array). 检测到click后,我们检查点击目标是否属于导航(在阵列中)。

Try to go up in DOM tree from target element. 尝试从目标元素进入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> 

Explanation - i start with e.target node and go up, there are to endings - one if we find parent which is matching searching element - this means we are inside or we are this element, or second we go to end of tree - we are outside. 说明-我从e.target节点开始,然后到结尾-如果找到与搜索元素匹配的父对象,则是一个结局-这意味着我们在其中,或者是这个元素,或者第二个结局是在树的末端-我们在外面。

This method can be improved by adding for example how much levels we should go up. 可以通过添加例如我们应该提高多少级别来改进此方法。

In this current problem usage of isInside function would be like this: 在当前问题中, isInside函数的用法如下:

function closeAll(e) {
   if (!isInside(nav,e.target) && !isInside(navToggle,e.target) ) {
      nav.classList.remove("main-nav--open");
   }
}

you can use jquery method "closest" 您可以使用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 return array of tree structure which can be used to find parents of target element. event.path返回树结构的数组,可用于查找目标元素的父级。

replace js code with : 用以下代码替换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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM