尽管使用addEventListener在父级上设置了单击处理程序,但在子div触发器操作上单击事件(事件冒泡已禁用))

时间:2015-12-06 03:20:57

标签: javascript

我有三个div框

第一个div主的ID为"main",其中包含另外两个标识为"menu_header""menu_options"

的框

这是我的HTML

<div id="main">
 <div id="menu_header">
  </div>
  <div id="menu_options">
  </div>
</div>
<span>Something here</span>

这是我的CSS

#main{
  display:table-cell;
  position:relative;
  top:100px;
  border:solid purple;
}
#menu_header{
  position:relative;
  border:solid black;
  background:red;
  width:100px;
  top:200px;
  height:100px;
 /* -moz-transition-property:bottom;
  -moz-transition-duration:2s;
  transition-property:top;
  transition-duration:1s;*/
}
#menu_options{
  background:blue;
  position:absolute;
  bottom:0%;
  border:solid black;
  width:100px;
  height:100px;
}
/*#menu_header:active{
  top:100px;
}*/

(忽略css过渡,因为它被注释掉了)

这是我的javascript

function test(e){
 //if(e.target.id=="menu_options"){return};
 $('#menu_header').animate({top:'-10'},1000);
  //var t=document.getElementById('menu_header')
 // t.setAttribute('top','40px');
  t.style="position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
}
document.getElementById('main').addEventListener('click',test,false)

最后这是我的实验室鼠标jsfiddle链接 http://jsfiddle.net/repzeroworld/ev7k688s/

在这种情况下,当我在我的父容器上设置一个id为"main"的点击事件处理程序时,除了点击这个父ID为"menu_options"的容器子div之外,一切都运行正常还会触发处理程序

我在下面找到了这个链接,但不知怎的,这里的event.propogation()解决方案似乎不适用于我的情况。

clicking on child element also triggers click event on it parent

一个令人讨厌的黑客攻击,以防止在子div捕获事件时执行任何操作

if(e.target.id=="menu_header"){return};

以上我在我的javascript代码中注释掉了。

问题: 尽管我在"menu_options"上设置了"main"以防止事件冒泡,但为什么ID为false的子div从父容器中捕获了标识为add EventListener的事件。

3 个答案:

答案 0 :(得分:3)

原因

false传递给.addEventListener()不会禁用冒泡。它只是使事件在冒泡阶段而不是捕获阶段发生。

当事件发生时,它从DOM的根开始并进入“捕获”阶段。这意味着事件从document发送到event.target,触发它在路上找到的任何“捕获”处理程序。

一旦到达event.target,它就会反转过程,然后遍历到document,调用它找到的任何“冒泡”处理程序。

因为你传递false作为第三个参数,处理程序将在最后一个“冒泡”阶段被调用。

所以你看,这并没有阻止嵌套元素调用处理程序。

解决方案

如果想要在单击实际元素时调用处理程序,而没有其子代,只需在this不等于e.target时停止处理程序。

function test(e){
   if (this != e.target)
      return;

   $('#menu_header').animate({top:'-10'},1000);
   var t=document.getElementById('menu_header')
   t.setAttribute('top','40px');
   t.style="position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
}
document.getElementById('main').addEventListener('click',test,false)

答案 1 :(得分:1)

您可以按2场景限制事件冒泡。 1.将Click事件放在每个DOM对象上,表示子对象为父对象并放入event.stropPropagation()。 2.使用e.target.id识别DOM对象并返回“false”。[我们正在使用此]

以下代码

<script>
        function test(e) {
            if (e.target.id == "menu_header") { return }
            else if (e.target.id == "menu_options") { return }
            $('#menu_header').animate({ top: '-10' }, 1000);
            var t = document.getElementById('menu_header')
            t.setAttribute('top','40px');
            t.style = "position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
        }
         window.onload = function () {
        document.getElementById('main').addEventListener('click', test, false);
    }
</script>

答案 2 :(得分:1)

尝试停止在子元素中传播。请参阅here

function test(){
 $('#menu_header').animate({top:'10'},1000);
  //var t=document.getElementById('menu_header')
 // t.setAttribute('top','40px');
  //t.style="position:relative;border:solid black;background:red;width:100px;top:60px;height:100px;"
}

function stopPropagation(e){
    e.stopPropagation();
}

document.getElementById('main').addEventListener('click',test,false);

document.getElementById('menu_header').addEventListener('click',stopPropagation,false);