posts - 193,  comments - 520,  trackbacks - 0

          DOM事件標(biāo)準(zhǔn)定義了兩種事件流,這兩種事件流有著顯著的不同并且可能對(duì)你的應(yīng)用有著相當(dāng)大的影響。這兩種事件流分別是捕獲和冒泡。和許多Web技術(shù)一樣,在它們成為標(biāo)準(zhǔn)之前,Netscape和微軟各自不同地實(shí)現(xiàn)了它們。Netscape選擇實(shí)現(xiàn)了捕獲事件流,微軟則實(shí)現(xiàn)了冒泡事件流。幸運(yùn)的是,W3C決定組合使用這兩種方法,并且大多數(shù)新瀏覽器都遵循這兩種事件流方式。

          默認(rèn)情況下,事件使用冒泡事件流,不使用捕獲事件流。然而,在Firefox和Safari里,你可以顯式的指定使用捕獲事件流,方法是在注冊(cè)事件時(shí)傳入useCapture參數(shù),將這個(gè)參數(shù)設(shè)為true。下面用個(gè)例子分別來(lái)測(cè)試這兩種事件流。

          1、冒泡事件流
          當(dāng)事件在某一DOM元素被觸發(fā)時(shí),例如用戶在客戶名字節(jié)點(diǎn)上點(diǎn)擊鼠標(biāo),事件將跟隨著該節(jié)點(diǎn)繼承自的各個(gè)父節(jié)點(diǎn)冒泡穿過(guò)整個(gè)的DOM節(jié)點(diǎn)層次,直到它遇到依附有該事件類型處理器的節(jié)點(diǎn),此時(shí),該事件是onclick事件。在冒泡過(guò)程中的任何時(shí)候都可以終止事件的冒泡,在遵從W3C標(biāo)準(zhǔn)的瀏覽器里可以通過(guò)調(diào)用事件對(duì)象上的stopPropagation()方法,在Internet Explorer里可以通過(guò)設(shè)置事件對(duì)象的cancelBubble屬性為true。如果不停止事件的傳播,事件將一直通過(guò)DOM冒泡直至到達(dá)文檔根。

          測(cè)試的HTML文件,其中用到了mootools-release-1.11.js,對(duì)mootools的代碼進(jìn)行了改動(dòng):
          addListener: function(type, fn,setCapture){
                      
          if (this.addEventListener) this.addEventListener(type, fn, setCapture);
                      
          else {
                          
          this.attachEvent('on' + type, fn);
                          
          if (setCapture) this.setCapture(true);
                      }
                      
          return this;
                  }
               
          給addListener方法里增加了setCapture參數(shù),用于測(cè)試捕獲事件流。
          <body>
          <div  id="dd1-ct" style="width:400px;height:400px;border:1px solid #999;padding:2px">Container
              
          <div id="dd1-item1" style="width:200px;height:200px;border:1px solid #999;padding:2px">Item1
                  
          <div  id="dd1-item2" style="width:100px;height:100px;border:1px solid #999;padding:2px">Item2</div>
              
          </div>  
          </div>
          <div id='rh'></div>
          </body>

          效果:

          js:
          fn1=function(e){
          //    e.stopPropagation();
              $('rh').innerHTML+='Item1 clicked!******';
          };

          fn2
          =function(e){
          //    e.stopPropagation();
              $('rh').innerHTML+='Item2 clicked!-------';
          };

          fn
          =function(e){
          //    e.stopPropagation();
              $('rh').innerHTML+='Container clicked!&&&&&&&&';
          };
             
          $('dd1
          -item2').addListener('click', fn2.bindWithEvent(),false);       
          $('dd1
          -item1').addListener('click', fn1.bindWithEvent(),false);
          $('dd1
          -ct').addListener('click', fn.bindWithEvent(),false);


          測(cè)試結(jié)果ie和ff下效果一致:?jiǎn)螕鬷tem2,會(huì)依次觸發(fā)fn2、fn1、fn;單擊item1,會(huì)依次觸發(fā)fn1、fn;單擊Container,只會(huì)觸發(fā)fn;當(dāng)在任何一個(gè)事件處理器里調(diào)用e.stopPropagation();都會(huì)阻止事件的冒泡。

          2、捕獲事件流
          事件的處理將從DOM層次的根開始,而不是從觸發(fā)事件的目標(biāo)元素開始,事件被從目標(biāo)元素的所有祖先元素依次往下傳遞。在這個(gè)過(guò)程中,事件會(huì)被從文檔根到事件目標(biāo)元素之間各個(gè)繼承派生的元素所捕獲,如果事件監(jiān)聽器在被注冊(cè)時(shí)設(shè)置了useCapture屬性為true,那么它們可以被分派給這期間的任何元素以對(duì)事件做出處理;否則,事件會(huì)被接著傳遞給派生元素路徑上的下一元素,直至目標(biāo)元素。事件到達(dá)目標(biāo)元素后,它會(huì)接著通過(guò)DOM節(jié)點(diǎn)再進(jìn)行冒泡。

          這里ie與ff存在著很大的差異,甚至ie6與ie7的表現(xiàn)也各不相同,所以分開測(cè)試。

          a、ff
          事件從從DOM層次的根開始往下傳遞時(shí),會(huì)被useCapture屬性為true的事件監(jiān)聽器所捕獲,而到達(dá)目標(biāo)元素再?gòu)哪繕?biāo)元素冒泡時(shí),則會(huì)被useCapture屬性為false的事件監(jiān)聽器所捕獲。當(dāng)在任何一個(gè)事件處理器里調(diào)用e.stopPropagation();都會(huì)阻止事件的傳播。

          b、ie6
          用事實(shí)說(shuō)話:

          第一種情況:
          $('dd1-item2').addListener('click', fn2.bindWithEvent(),true);       
          $('dd1
          -item1').addListener('click', fn1.bindWithEvent(),true);
          $('dd1
          -ct').addListener('click', fn.bindWithEvent(),true);

          單擊瀏覽器的任何位置,都只是觸發(fā)fn;

          第二種情況:
          $('dd1-item2').addListener('click', fn2.bindWithEvent(),true);       
          $('dd1
          -item1').addListener('click', fn1.bindWithEvent(),true);
          $('dd1
          -ct').addListener('click', fn.bindWithEvent(),false);

          單擊瀏覽器的任何位置,會(huì)依次觸發(fā)fn1、fn;

          第三種情況:
          $('dd1-item2').addListener('click', fn2.bindWithEvent(),true);       
          $('dd1
          -item1').addListener('click', fn1.bindWithEvent(),false);
          $('dd1
          -ct').addListener('click', fn.bindWithEvent(),false);

          單擊瀏覽器的任何位置,會(huì)依次觸發(fā)fn2、fn1、fn;

          結(jié)論:如果HTML元素捕獲了通過(guò)該元素的setCapture()方法對(duì)這個(gè)元素的設(shè)置,依附于該元素的處理器將會(huì)被事件觸發(fā),即使setCapture()方法
          被調(diào)用的這個(gè)元素不在目標(biāo)元素的祖先路徑中。事實(shí)上你甚至單擊瀏覽器的非頁(yè)面部分都會(huì)觸發(fā)事件處理器。并且事件一旦被捕獲就不會(huì)繼續(xù)再
          往下傳播(即使該元素在目標(biāo)元素的祖先路徑中),而是立刻冒泡。e.stopPropagation();會(huì)阻止事件的冒泡。
           
          c、ie7
          測(cè)試效果與冒泡事件流一致。將對(duì)捕獲事件流的支持干掉了?
           
          結(jié)論:正如mootools所做的,避免捕獲事件流。




          http://www.aygfsteel.com/ronghao 榮浩原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:)
          posted on 2008-03-02 14:54 ronghao 閱讀(2008) 評(píng)論(0)  編輯  收藏 所屬分類: ajax相關(guān)
          <2008年3月>
          2425262728291
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          關(guān)注工作流和企業(yè)業(yè)務(wù)流程改進(jìn)。現(xiàn)就職于ThoughtWorks。新浪微博:http://weibo.com/ronghao100

          常用鏈接

          留言簿(38)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          常去的網(wǎng)站

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 张家港市| 逊克县| 峨山| 莱阳市| 合川市| 滁州市| 三门峡市| 靖江市| 罗甸县| 贵州省| 攀枝花市| 色达县| 麻城市| 吉林市| 乡宁县| 额敏县| 镇雄县| 龙江县| 北川| 筠连县| 广丰县| 和静县| 广饶县| 华坪县| 嵩明县| 潼南县| 卓尼县| 南和县| 阆中市| 油尖旺区| 泰来县| 涟水县| 龙海市| 黄大仙区| 衡阳市| 岑溪市| 正安县| 东辽县| 临洮县| 松阳县| 丘北县|