zoukankan      html  css  js  c++  java
  • 利用事件冒泡和阻止事件冒泡的例子

    页面中的评分界面,大家一定都很熟悉,现在假如我开了一家饭店,我需要一个在我们的网页上能让顾客对我的饭店进行打分。首先,我们需要两张星星的图片,一张是灰的的星星,一张是黄色的星星,我们分别命名为star.gif和star2.gif。如下图所示:

    灰色星星黄色星星

    接下来,我们开始编写打分程序的代码:

     <!--相关的html结构-->
     <h1>费墨的饭店</h1>
     <p>hygiene</p>
     <p class="J_rate">
      <img src="star.gif" title="很烂" />
      <img src="star.gif" title="一般" />
      <img src="star.gif" title="还好" />
      <img src="star.gif" title="较好" />
      <img src="star.gif" title="很好" />
     </p>
     <p>price</p>
     <p class="J_rate">
      <img src="star.gif" title="很烂" />
      <img src="star.gif" title="一般" />
      <img src="star.gif" title="还好" />
      <img src="star.gif" title="较好" />
      <img src="star.gif" title="很好" />
     </p>
     <p>flavour</p>
     <p class="J_rate">
      <img src="star.gif" title="很烂" />
      <img src="star.gif" title="一般" />
      <img src="star.gif" title="还好" />
      <img src="star.gif" title="较好" />
      <img src="star.gif" title="很好" />
     </p>
     <script type="text/javascript">
      //DOM,event  package
      var GLOBAL={};
      GLOBAL.namespace=function(str){
        var arr=str.split("."),o=GLOBAL;
        for(var i=(arr[0]=="GROBAL") ? 1:0; i<arr .length;i++){
            //相当于GLOBAL{arr[i]:{}}
          o[arr[i]]=o[arr[i]] || {};
          o=o[arr[i]];
        }
      }
      GLOBAL.namespace("Dom");
      GLOBAL.Dom.getElementsByClassName=function(str,root,tag){
        //是否存在root,并且是否已经与DOM节点挂钩。不存在则赋于document.body
        if(root){
          root=typeof root=="string" ? document.getElementById("root"):root;
        }
        else{
          root=document.body;
        }
        //是否存在tag,不存在则为通配符
        tag=tag||"*";
        //在root里取得tag的数组,arr数组备用储存结果
        var els=root.getElementsByTagName(tag),arr=[];
        //遍历取得的每个标签
        for(var i=0,n=els.length;i<n;i++){
          //遍历标签的每个class
          for(var j=0,k=els[i].className.split(" "),l=k.length;j<l;j++){
              //查找匹配项,并跳出遍历className的循环
            if(k[j]==str){
              arr.push(els[i]);
              break;
            }
          }
        }
        return arr;
      }
      GLOBAL.namespace("Event");
      GLOBAL.Event.on=function(node,eventType,handler,scope){
        //确保node与DOM节点挂钩
        node=typeof node=="string" ? document.getElementById(node) : node;
        scope=scope || node;
        //如果是IE
        if(document.all){
          node.attachEvent("on"+eventType,function(){handler.apply(scope,arguments)});
        }
        else{
          node.addEventListener(eventType,function(){handler.apply(scope,arguments)},false);
        }
      }
      function Rate(rateRoot){
        var root=typeof rateRoot=="string" ? document.getElementById(rateRoot) : rateRoot;
        var items=root.getElementsByTagName("img");
        var imgs=["star.gif","star2.gif"];
        var rateFlag;
        for(var i=0,n=items.length;i<n;i++){
          //记录DOM索引
          items[i].index=i;
          //鼠标滑过效果
          GLOBAL.Event.on(items[i],"mouseover",function(){
            //点击过后,直接跳出,不执行该函数
            if(rateFlag) return;
            //遍历每个星星,如果在点击索引位置之前的变黄色,之后的为灰色
            for(var j=0;j<n;j++){
              if(j<=this.index){
                items[j].src=imgs[1];
              }
              else{
                items[j].src=imgs[0];
              }
            }
          });
          //鼠标滑出,但未点击,所有星星变成灰色
          GLOBAL.Event.on(items[i],"mouseout",function(){
            if(rateFlag) return;
            for(var j=0;j<n;j++){
              items[j].src=imgs[0];
            }
          });
          //鼠标点击,显示打分
          GLOBAL.Event.on(items[i],"click",function(){
            if(rateFlag) return;
            rateFLag=true;
            alert("您打了"+(this.index+1)+"分");
          });
        }
      }
      //实例化rate
      var rateNodes=GLOBAL.Dom.getElementsByClassName("J_rate");
      for(var i=0,n=rateNodes.length;i<n;i++){
        new Rate(rateNodes[i]);
      }
     </script>

    在上述代码中,对每个星星监听了mouseover、mouseout和click事件。其效果等同于:

     <p class="J_rate">
      <img src="star.gif" title="很烂" onmouseover="..." onmouseout="..." onclick="..." />
      <img src="star.gif" title="一般" onmouseover="..." onmouseout="..." onclick="..." />
      <img src="star.gif" title="还好" onmouseover="..." onmouseout="..." onclick="..." />
      <img src="star.gif" title="较好" onmouseover="..." onmouseout="..." onclick="..." />
      <img src="star.gif" title="很好" onmouseover="..." onmouseout="..." onclick="..." />
     </p>

    之前我们提到过事件冒泡,利用事件冒泡我们可以进一步优化代码。代码如下:

    function Rate(rateRoot){
        var root=typeof rateRoot=="string" ? document.getElementById(rateRoot) : rateRoot;
        var items=root.getElementsByTagName("img");
        var imgs=["star.gif","star2.gif"];
        var rateFlag;
        for(var i=0,n=items.length;i<n ;i++){
          //记录DOM索引
          items[i].index=i;
        }
        //鼠标滑过效果
        GLOBAL.Event.on(root,"mouseover",function(e){
          //点击过后,直接跳出,不执行该函数
          if(rateFlag) return;
          var target=e.target || e.srcElement;
          if(target.tagName.toLowerCase() !="img") return;
          //遍历每个星星,如果在点击索引位置之前的变黄色,之后的为灰色
          for(var i=0,n=items.length;i<n;i++){
            if(i<=target.index){
              items[i].src=imgs[1];
            }
            else{
              items[i].src=imgs[0];
            }
          }
        });
        //鼠标滑出,但未点击,所有星星变成灰色
        GLOBAL.Event.on(root,"mouseout",function(e){
          if(rateFlag) return;
          var target=e.target || e.secElement;
          for(var i=0,n=items.length;i<n;i++){
            items[i].src=imgs[0];
          }
        });
        //鼠标点击,显示打分
        GLOBAL.Event.on(root,"click",function(e){
          if(rateFlag) return;
          rateFLag=true;
          var target=e.target || e.srcElement;
          alert("您打了"+(target.index+1)+"分");
        });
      }
      //实例化rate
      var rateNodes=GLOBAL.Dom.getElementsByClassName("J_rate");
      for(var i=0,n=rateNodes.length;i<n;i++){
        new Rate(rateNodes[i]);
      }
     </script>

    冒泡的思路是在祖先节点上监听事件,结合event.target/event.srcElement来实现最终效果,其效果等同于如下代码:

    <p class="J_rate" onmouseover="..." onmouseout="..." onclick="...">
      <img src="star.gif" title="很烂" />
      <img src="star.gif" title="一般" />
      <img src="star.gif" title="还好" />
      <img src="star.gif" title="较好" />
      <img src="star.gif" title="很好" />
     </p>

    利用事件冒泡机制可以让事件挂钩更干净,有效减小内存的开销。

    阻止事件冒泡

             JS事件流中有一种事件被称为“冒泡事件”,当一个元素被触发一个事件时,该目标元素上的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上冒,到达水平面时,它才消失。在这个过程中,如果你只希望触发目标元素上的事件,而不想它传播到祖先元素上去,那么你需要在“泡泡”离开对象之前刺破它。下面,就以一个简单的Demo来演示下JS如何阻止事件冒泡:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
       <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>js阻止事件冒泡的DEMO</title>
    <script type="text/javascript">
    	//阻止冒泡的方法
    	function stopPP(e)
    	{
    		var evt = e || window.event;
    		//IE用cancelBubble=true来阻止而FF下需要用stopPropagation方法
    		evt.stopPropagation ? evt.stopPropagation() : (evt.cancelBubble=true);
    	}
    </script>
    </head>
    <body>
    <div style="margin: 150px 400px; 700px; height: 550px; background-color: #878788;" onclick="alert('最外层div上的onclick事件');">
    <h2>最外层div上的onclick事件</h2>
    <div style="margin: 100px;  500px; height: 300px; background-color: #545444;" onclick="stopPP(arguments[0]);alert('中间层div上的onclick事件');">
    <h3>中间层div上的onclick事件</h3>
    <div style="margin: 60px 100px; height: 100px;  300px; background-color: red;" onclick="stopPP(arguments[0]);alert('最内层div上的onclick事件');">
    <h4>最内层div上的onclick事件”</h4>
    </div>
    </div>
    </div>
     
    </body>
    </html>
  • 相关阅读:
    ios8 xcode6 下的启动界面设置和图标设置
    写一些有关android的东西吧,那时候玩android时候的一些笔记
    使用sqlite3 有关tableview删除cell的问题
    iOS 使用CLGeocoder获取地理位置
    ios 解决有关火星坐标的问题
    iOS 火星坐标相关整理及解决方案汇总(转)
    IOS开发UI篇之──自定义UIActionSheet
    python中新式类和经典类的区别
    python中几个常用的算术函数
    多线程
  • 原文地址:https://www.cnblogs.com/fumj/p/2730527.html
Copyright © 2011-2022 走看看