zoukankan      html  css  js  c++  java
  • JS中的事件冒泡问题

    onMouseOver,onMouseOut,onClick等都存在事件冒泡

    比如代码如下:
    <div onClick="alert('你点了div');">
    <input type="button" value="div中的按钮" onClick="alert('你点了button')" />
    </div>

    div中有一个button

    事实是,当你单击了按钮,div的onClick事件也会执行,不单是这样,所有button的父级对像都会执行onClick包括body, 这显然不是我们想要的.

    解决办法:
    阻止事件冒泡
    function zuzhi(e){
        if (e && e.stopPropagation ) { //如果提供了事件对象,则这是一个非IE浏览器
            e.stopPropagation();
        }else{//否则,我们需要使用IE的方式来取消事件冒泡 
            window.event.cancelBubble = true;
        }
    }
    上面的代码就成了这样:
    <script type="text/javascript">
    function zuzhi(e){
    if (e && e.stopPropagation ) { //如果提供了事件对象,则这是一个非IE浏览器
     e.stopPropagation();
    }
    else{//否则,我们需要使用IE的方式来取消事件冒泡 
     window.event.cancelBubble = true;
    }
    }
    </script>
     
    <div onClick="alert('你点了div');">
    <input type="button" value="div中的按钮" onClick="(function(e){alert('你点了button');zuzhi(e);})()" />
    </div>

    上面说的是onClick事件,子对像阻止了事件冒泡,但要是父对像的事件,子对像触发怎么怎么办泥?
    还是拿一个div和一个button打比方:
    <div onMouseOver="document.getElementById('msg').innerHTML+='\r我进来了'" onMouseOut="document.getElementById('msg').innerHTML+='\r我出去了'">
        <input type="button" value="按钮" />
    </div>
    <div id="msg"></div><!--这里只是用记录事件执行的-->
    本来很明了的事情也出错了,你会发鼠标移入button上时候先后执行VID的onMouseOut和onMouseOver事件,其了怪了,这管button什么事.这就是事件冒泡.
    这时候我也和处理onClick事件一样给button的onMouseOut 和 onMouseOver事件组织事件冒泡:
    <script type="text/javascript">
    function zuzhi(e){
    if (e && e.stopPropagation ) { //如果提供了事件对象,则这是一个非IE浏览器
    e.stopPropagation();
     }
    else{//否则,我们需要使用IE的方式来取消事件冒泡
    window.event.cancelBubble = true;
    }
    }
    </script>
    <div onMouseOver="document.getElementById('msg').innerHTML+='\r我进来了'" onMouseOut="document.getElementById('msg').innerHTML+='\r我出去了'">
        <input type="button" value="按钮" onMouseOut="(function(e){zuzhi(e);})();"  onMouseOver="(function(e){zuzhi(e);})();" />
    </div>
    <div id="msg"></div><!--这里只是用记录事件执行的-->
    啊哦,问题来了,当鼠标进入button时执行了div的onMouseOut,而鼠标出button时执行了div的onMouseOver,头都大了,怎么办?
    实验说明当鼠标进入子标签的一定会执行onMouseOut事件,和子事件冒泡似乎无关了.那怎么解决呢.
    在这个情况下我两种方法:
    1.给onMouseOut执行语句时加个延迟执行.不阻止子对像的事件冒泡,这样操作简单,可能很多效果本事就会用到延迟执行.
    <script type="text/javascript">
     
    var $in, $out;
     
    function M_in() {
        clearTimeout($out);
        $
    in= setTimeout(function() {document.getElementById('msg').innerHTML +='\r我进来了'},100)
      }
     
    function M_out() {
        clearTimeout($
    in);
        $out
    = setTimeout(function() {document.getElementById('msg').innerHTML +='\r我出去了'},100)
      }
    </script>
    <div onMouseOver="M_in();" onMouseOut="M_out();">
      <input type="button" value="按钮"/>
    </div>
    <div id="msg">
    </div><!--这里只是用记录事件执行的-->
    这样改了之后你会发现,无论你把鼠标移进按钮还是移出按钮,执行的都好像只执行了 onMouseOver 事件; 有时候虽然多次执行onMouseOver但关不改变什么,就能用这个方法解决;
     
    2.执行时判断事件对像是子对像触发,是就停止执行;
    IE和其它浏览器用的方法不一样,所以代码会多一点(经过IE6789,FF,Chrome测试);
    <script type="text/javascript">
      
    function M_out(e) {
        
    var obj = document.getElementById('fff');
        
    if (window.event && !e.relatedTarget) {
          
    if (obj.contains(event.toElement)) {
            
    return
          }
        } 
    else if (e && e.relatedTarget) {
          
    if (obj.contains(e.relatedTarget)) {
            
    return
          }
        };
        document.getElementById(
    'msg').innerHTML += '我出去了<br/>'
      }
      
    function M_in(e) {
        
    var obj = document.getElementById('fff');
        
    if (window.event && !e.relatedTarget) {
          
    if (obj.contains(event.fromElement)) {
            
    return
          }
        } 
    else if (e && e.relatedTarget) {
          
    if (obj.contains(e.relatedTarget)) {
            
    return
          }
        };
        document.getElementById(
    'msg').innerHTML += '我进来了<br/>'
      }
    </script>
    <div id="fff" onMouseOver="M_in(event);" onMouseOut="M_out(event);" style="padding:10px; margin:0 auto; 700px; border:3px solid #00F">
      <input id="bt1" type="button" value="按钮" />
    </div>
    <div id="msg" style="padding:5px;border:1px solid #00F">
    </div><!--这里只是用记录事件执行的-->
    说明:mouseover中relatedTarget指向鼠标来自的元素,而mouseout中的relatedTarget指向的是鼠标去向的那个元素。IE中则是toElement和fromElement;
    如果直接用JS的事件绑定,判断上会简单很多:
    <script type="text/javascript">
      window.onload 
    = function() {
        
    var obj = document.getElementById("fff");
        
    var msg = document.getElementById("msg");
        obj.onmouseout 
    = function(e) {
          
    if (e) {
            
    if (obj.contains(e.relatedTarget)) {
              
    return
            }
          } 
    else if (event) {
            
    if (obj.contains(event.toElement)) {
              
    return
            }
          };
          msg.innerHTML 
    += '我出去了<br/>'
        }
        obj.onmouseover 
    = function(e) {
          
    if (e) {
            
    if (obj.contains(e.relatedTarget)) {
              
    return
            }
          } 
    else if (event) {
            
    if (obj.contains(event.fromElement)) {
              
    return
            }
          };
          msg.innerHTML 
    += '我进来了<br/>'
        }
      }
    </script>
    <div id="fff" style="padding:10px; margin:0 auto; 700px; border:3px solid #00F">
      <input id="bt1" type="button" value="按钮" />
    </div>
    <div id="msg" style="padding:5px;border:1px solid #00F">
    </div><!--这里只是用记录事件执行的-->
     
    补充
    1. 不是所有的事件都能冒泡。以下事件不冒泡:blur、focus、load、unload。 
    2.阻止冒泡并不能阻止对象默认行为。比如submit按钮被点击后会提交表单数据,这种行为无须我们写程序定制。 
  • 相关阅读:
    javascript 如何获取return回来的对象值
    遮罩层背景设置
    Javascript跨域请求的几种解决方法
    手机端viewport的设置规范
    javascript定义类和类的实现
    javascript 中对this关键字的一些理解
    实例化对象的时候。其实就是调用构造函数
    Javascript定义类(class)的三种方法
    javascript面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)
    JavaScript判断横屏/竖屏
  • 原文地址:https://www.cnblogs.com/whyoop/p/2542233.html
Copyright © 2011-2022 走看看