利用事件冒泡和阻止事件冒泡的例子

页面中的评分界面,大家一定都很熟悉,现在假如我开了一家饭店,我需要一个在我们的网页上能让顾客对我的饭店进行打分。首先,我们需要两张星星的图片,一张是灰的的星星,一张是黄色的星星,我们分别命名为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;width: 700px; height: 550px; background-color: #878788;" οnclick="alert('最外层div上的onclick事件');">
<h2>最外层div上的onclick事件</h2>
<div style="margin: 100px; width: 500px; height: 300px; background-color: #545444;" οnclick="stopPP(arguments[0]);alert('中间层div上的onclick事件');">
<h3>中间层div上的onclick事件</h3>
<div style="margin: 60px 100px; height: 100px; width: 300px; background-color: red;" οnclick="stopPP(arguments[0]);alert('最内层div上的onclick事件');">
<h4>最内层div上的onclick事件”</h4>
</div>
</div>
</div>
 
</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值