2015年12月5日 星期六

JavaScript, jQuery 的Event機制 (Capturing, Bubbling)

在Javascript的W3C標準中,當Evnet(事件)發生時,例如click事件、animationEnd事件、hover事件等,Event會以由外到內(Capturing)、再由內到外(Bubbling)的方式傳遞。

我們可以用JavaScript的方法,addEventListener(eventName , callbackFunction , capturOrBubble)
來設置Evnet的監聽器,其中

第一個參數eventName為一個String,表示事件名稱,跟jQuery的bind()及one()不同,不可用空白分隔多個事件。

第二個參數是一個callback方法,可以選擇傳入event參數來得到event資訊,例如可以用event.target或event.srcElement (IE適用) 來得到Event作用的JavaScript對像。

我們也可以用Jquery的方法,bind(eventName,callbackFunction),來做到一樣的事情,不過要要注意bind()的callbackFunction傳入的event不是JavaScript的Event物件,而是被包裹成jQuery版的Event物件,雖然一樣有event.target,但是確沒有event.srcElement,如果要拿到JavaScript版的Event物件,可以使用event.origianlEvent來得到。

現在用下面這個例子來說明:

html:

<div id='1'>
  <div id='2'>
    <div id='3' class='animClass'>Watch me move</div>
  </div>
</div>
<div id='text'></div>


CSS :
.animClass {
  animation-name: myAnim;
  animation-duration: 1s;
}



@keyframes myAnim {
  0% {
    padding-left: 100%;
  }
  100% {
    padding-left: 0%;
  }
}

JavaScript (使用addEventListener) :

document.getElementById('1').addEventListener('animationend', function (event) {
  $('#text').html($('#text').html() + '#1 catched animation end from #' + event.target.id + '! (Capturing)</br>');
}, true);

document.getElementById('2').addEventListener('animationend', function (event) {
  $('#text').html($('#text').html() + '#2 catched animation end from #' + event.target.id + '! (Capturing) </br>');
}, true);

document.getElementById('3').addEventListener('animationend', function (event) {
  $('#text').html($('#text').html() + '#3 catched animation end from #' + event.target.id + '! (Capturing) </br>');
}, true);

document.getElementById('1').addEventListener('animationend', function (event) {
  $('#text').html($('#text').html() + '#1 catched animation end from #' + event.target.id + '! (Bubbling)</br>');
}, false);

document.getElementById('2').addEventListener('animationend', function (event) {
  $('#text').html($('#text').html() + '#2 catched animation end from #' + event.target.id + '! (Bubbling) </br>');
}, false);

document.getElementById('3').addEventListener('animationend', function (event) {
  $('#text').html($('#text').html() + '#3 catched animation end from #' + event.target.id + '! (Bubbling) </br>');
}, false);

其結果是:

Watch me move
#1 catched animation end from #3! (Capturing)
#2 catched animation end from #3! (Capturing)
#3 catched animation end from #3! (Capturing)
#3 catched animation end from #3! (Bubbling)
#2 catched animation end from #3! (Bubbling)
#1 catched animation end from #3! (Bubbling)

可以看到由動畫事件由外到內(由id=1到id=3)被Captur,由內到外(由id=3到id=1)Bubble。


接著是jQuery的bind()版本的例子,需注意的是,jQuery目前(ver 2.1.4)並沒有實現Capturing,只有Bubbling,因為IE為無支援Catpuring。 CSS及html都同上,只有JavaScript的code不一樣:

JavaScript (jQuery的bind()版本 ):

$('#1').bind('webkitAnimationEnd oanimationend msAnimationEnd animationend',function(event){
  $('#text').html($('#text').html() + '#1 catched animation end from ' + event.target.id + '! </br>');
});

$('#2').bind('webkitAnimationEnd oanimationend msAnimationEnd animationend',function(event){
  $('#text').html($('#text').html() + '#2 catched animation end from ' + event.target.id + '! </br>');
});

$('#3').bind('webkitAnimationEnd oanimationend msAnimationEnd animationend',function(event){
  $('#text').html($('#text').html() + '#3 catched animation end from ' + event.originalEvent.srcElement.id + '! </br>');
});


其結果是:
Watch me move
#3 catched animation end from #3!
#2 catched animation end from #3!
#1 catched animation end from #3! 

沒有留言 :

張貼留言