天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

Javascript 事件流和事件綁定

事件流

瀏覽器中的事件流意味著頁面上可有不僅一個,甚至多個元素響應(yīng)同一個事件。而這一個或多個元素響應(yīng)事件發(fā)生的先后順序在各個瀏覽器(主要針對IE和NETscape)上是不同的。

冒泡型事件(Dubbed Bubbling)

IE上的解決方案就是冒泡型事件(Dubbed Bubbling)。冒泡型事件的基本思想是,事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對象)的順序觸發(fā)。

示例(1):點擊我觸發(fā)冒泡型事件流

示例(1)的XHTML代碼結(jié)構(gòu):

<span id="cnt0">
     <a href=”#1″ id=”link0″>點擊我觸發(fā)冒泡型事件流</a>
</span>

這個示例里我同時給span和a標(biāo)簽綁定了click事件,大家看到了,我們點擊這個a標(biāo)簽,一次點擊(click)同時觸發(fā)了兩個元素a和span的事件。先觸發(fā)的是綁定給a標(biāo)簽的click事件,然后觸發(fā)的是span標(biāo)簽的click事件。也就是前面提到的“頁面上可有不僅一個,甚至多個元素響應(yīng)同一個事件”和“事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對象)的順序觸發(fā)”。

這個示例里我們點擊的第一目標(biāo)是a標(biāo)簽這個鏈接,它就是前面提到的“最特定的事件目標(biāo)”,然后才是span這個相對“不特定的事件目標(biāo)”。再看看我的XHTML代碼結(jié)構(gòu),你會發(fā)現(xiàn)a標(biāo)簽包含在span標(biāo)簽中,也就是說span是a標(biāo)簽的父節(jié)點,如果大家還不是很清晰的知道他們之間的關(guān)系,讓我們看看下面的這個DOM樹的結(jié)構(gòu)圖:

示例(1)

事件觸發(fā)的順序是從最特定的目標(biāo),沿著DOM樹不斷的向上觸發(fā)click事件,就像氣泡從下一直上冒的過程一樣。“冒泡型”也就是這么得來的,也很形象。這里要說明的是,由于我只給a和span綁定了click事件,所以“冒”到span就到頂了,如果你也給包含他們的p標(biāo)簽還有document綁定click事件,這個冒泡的過程就會一直延續(xù)到document的事件觸發(fā)才結(jié)束。

另外要說明的是,在IE5.5中冒泡的最高層DOM節(jié)點為document,IE6中則可以支持html節(jié)點。在Mozllia1.0及之后的版本也支持冒泡,而它則更可以冒到window窗口對象。

捕獲型事件(Event Capturing)

相對IE4.0,NETscape4.0則使用的是捕獲型事件的解決方案。這個事件觸發(fā)的過程則正好和冒泡相反――在捕獲型事件中,事件從最不精確的對象(document對象)開始觸發(fā),然后到最精確的對象。還是前面的示例,不過現(xiàn)在換由捕獲型事件觸發(fā)(當(dāng)然你需要在NETscape或Firefox中測試)。

示例(2):點擊我觸發(fā)捕獲型事件流

示例(2)的XHTML代碼結(jié)構(gòu):

<span id="cnt1">
     <a href=”#1″ id=”link1″>點擊我觸發(fā)捕獲型事件流</a>
</span>

事件觸發(fā)的循序正好跟前面的冒泡相反,這里我就不贅述了。

DOM 事件流

這個事件流則是W3C制定一個標(biāo)準(zhǔn)規(guī)范,它同時支持兩種事件流模式,不過是先發(fā)生捕獲型事件流,再發(fā)生冒泡型事件流。

DOM事件流最獨特的是,它支持文本節(jié)點也觸發(fā)事件(IE中這不支持)。不過說實話,我現(xiàn)在還看不出來讓文本節(jié)點支持事件有什么作用。

最后要說的是,根據(jù)最近大家在開發(fā)的實踐過程中的運用,我們一般都采取冒泡型的事件流觸發(fā)方式,這點我們的IE做的比較成功。至于原因,我想你可以通過上面的解釋可以看出,畢竟我們給元素觸發(fā)事件,肯定是希望從我們最希望先觸發(fā)(從最精確的)的那個開始。而DOM的先捕獲后冒泡我覺得只能用讓我很疑惑來形容我的感受。因為如果按照DOM的事件流,我們的事件要被觸發(fā)2次,而我們一般都只會選擇一個類型的事件流,值希望觸發(fā)一次,很難理解當(dāng)初W3C是怎么想的?!一個字――暈!可能我的理解能力有限,不過這是我的真是感受。

事件處理函數(shù)/監(jiān)聽函數(shù)

這里我不想做過多的介紹,我們知道在IE里使用attachEvent(”NAME_OF_EVENT_HANDLER”, fnHandler)給元素綁定事件,而在支持DOM事件流的瀏覽器里,則使用addEventListener(”NAME_OF_EVENT_HANDLER”, fnHandler, isCapture)。前面我控制FIREFOX中觸發(fā)捕獲事件流,就是通過設(shè)置isCapture(ture:捕獲;false:冒泡)做到的。還有就是我們傳統(tǒng)element.onclick或者element['on'+eventName],這個是所有瀏覽器都支持的事件綁定的監(jiān)聽器,而且我測試的結(jié)果XP下的IE6~8、Firefox2.0~3.5、Safari4.0、Opera9.6.4、Chrome2.0.180都是以冒泡的事件流觸發(fā)的。更老的瀏覽器我就沒有測試過了,不過根據(jù)《Pro Javascript Techniques》里介紹,老的瀏覽器使用onclick這樣的事件綁定,觸發(fā)的也是冒泡事件流。如果你有興趣可以淘下那些古董瀏覽器,測試一番。不過還是有不支持冒泡的事件的,下面我們就講講。

那些事件是支持冒泡,那些不支持?

這個是比較有意思的,這里的總結(jié)都來自PPK在YAHOO的演講《Javascript Event》(推薦大家一定看看,很經(jīng)典!),簡單總結(jié)PPK的內(nèi)容,基本上只有onload、unload、focus、blur、submit和change事件是不支持冒泡的,這也是我在前面說“一般使用冒泡事件流”。自然向keydown、keypress、keyup、click、dbclick、mousedown、mouseout、mouseover、mouseup、mousemove。用PPK的話說,那就是“Mouse and Key Events”支持冒泡,而Interface Events(也就是《Javascript高級程序設(shè)計》里的HTML(HTML是來構(gòu)建interface的)事件。)則只支持捕獲。

他又說了下是,click是“最安全的”事件,它即支持冒泡,又支持捕獲。鼠標(biāo)事件可以觸發(fā)click,鍵盤事件也可以觸發(fā)click。還有就是在支持DOM事件的瀏覽器里,focus和blur是只支持捕獲的,所以如果你如果用到我下面給出的addEvent函數(shù),在給元素綁定focus或則blur事件時,bCapture一定要設(shè)置為true。那么這里就發(fā)生了一個問題,IE是不支持捕獲的,那不是觸發(fā)不了這連個事件?呵呵,是個嚴(yán)重的問題哦?不過在IE里使用focus和blur事件的時候,其實觸發(fā)的是IE的focusin和focusout,當(dāng)然這兩個事件也是只支持冒泡的。

PPK雖然這么說,但是我還是想實踐一下,于是我這里這么處理了下,window.onfocus = function(){alert('ok')},lnkOne.onfocus = demoClick;有趣的事情發(fā)生了!在IE6里,當(dāng)你點擊我的第一個示例鏈接,呵呵,視乎是即冒泡完了又捕獲了,在IE8中則只冒泡了,不過這個只是你點這個鏈接的時候發(fā)生的情況。接著我又算是試探性地“無意中”測試了下,點擊其他的應(yīng)用程序,又一個讓我意想不到的情況發(fā)生了,居然先觸發(fā)了window.onfocus,接著觸發(fā)了lnk.onfocus!!于是我立刻測試了IE6,一樣!視乎IE也“瘋狂”了一把,觸發(fā)了onfocus的捕獲哦,哈哈!!!難道IE也支持捕獲,IE也瘋狂???!!!!還是這個現(xiàn)象有其他的解釋??疑惑!?!?!!呵呵,起初我確實這么想,讓我驚喜了一把,不過仔細想了想,只是事件執(zhí)行順序的原因造成了這樣的假象。

呵呵,原來在IE6里,點擊鏈接,先觸發(fā)了onfocus,彈出提示‘A',然后關(guān)閉彈出的提示框窗口時,窗口又獲得了焦點,又觸發(fā)了window的焦點事件。然后是觸發(fā)了A標(biāo)簽的的click事件,然后關(guān)閉彈出的提示窗口時,又讓窗口獲得了焦點,然后又是A標(biāo)簽獲得焦點。而IE8測試正確的,當(dāng)觸發(fā)了click事件后,再關(guān)閉提示窗口的時候,就不在觸發(fā)window的focus。哎!空歡喜了一場,我還以為windows的IE支捕獲呢!!不過也不是完全沒有收獲,如果你也像我這么整了,你要注意IE6會折騰兩次的,不過只是在你點擊的時候才會這樣,如果用tab切換獲得焦點,就只會觸發(fā)A標(biāo)簽的focus事件了。

還有在Firefox(我測試的最新的3.5)中,可千萬別window.onfocus,不然你就掛了!很抱歉用FIREFOX看我這篇帖子的人,OK了幾次后,你就掛了!!呵呵!!!

What is ‘this'?

IE在前面給了我“驚喜”,this也給我驚喜。當(dāng)然主要是我以前沒有注意到,但是YAHOO的工程師們早以發(fā)現(xiàn)了。this這個關(guān)鍵字是根據(jù)上下文來決定的,在我們的事件綁定的功能函數(shù)里,this應(yīng)該是指向當(dāng)前的元素節(jié)點對象,應(yīng)該是一個Element對象。我想這個大家應(yīng)該好理解:

示例代碼:


<span id="cnt0">
     <a href=”#1″ id=”link0″>點擊我觸發(fā)捕獲型事件流</a>
</span>

<script type=”text/Javascript”>
var link = document.getElementById('link1′);
     link.onclick = function(){
          alert(this.tagName);
     };
</script>

這段代碼正式我在示例(1)中的處理方式,示例中this指向的a標(biāo)簽這個element對象,所以我們可以得到a標(biāo)簽的tagName這個屬性‘A'。示例(2)里,我使用一個兼容的事件監(jiān)聽函數(shù):


function addListener(el, event, fn, bCapture){
  var isCapture = bCapture ? bCapture : false;
  try {
    el.addEventListener(event, fn, isCapture);
  }
  catch (e) {
    try {
      el.attachEvent('on' + event, fn);
    }
    catch (e) {
      el['on' + event] = fn;
    }
  }
}

在我們的支持DOM事件流的瀏覽器里,我們也可以得到正確的提示this.tagName為‘A'。this出現(xiàn)問題就在IE中,當(dāng)我們使用attachEvent給元素綁定事件,現(xiàn)在你點擊下面的鏈接:

示例(3):What is ‘this'?

示例代碼:
<span id=”cnt2″>
    <a href=”#1″ id=”link2″>What is ‘this'?</a>
</span>

function whatIsThis(){
    if (this === window) {
        alert('This is a window object');
    }
    alert('So, This.tagName is:'+ ‘‘'+ this.tagName +''。');
}

<script type=”text/Javascript”>
var cntThree = document.getElementById('cnt2′), lnkThree = document.getElementById('link2′);

addListener(lnkThree, ‘click', whatIsThis);
addListener(cntThree, ‘click', whatIsThis);
</script>

看清楚了嗎?如果你在IE6~8中測試,那么你點的是window對象而不是一個a標(biāo)簽。暈倒!!!-_-! 所以你要小心,問題多多啊,要解決這個this關(guān)鍵字的問題,我給你的建議就是你可以考慮直接用傳統(tǒng)的'onclick'或者修改下前面的綁定事件監(jiān)聽的函數(shù):

修改后的代碼:

function addEvent(el, event, fn, obj, overrideContext, bCapture){
  var context = el, isCapture = bCapture ? bCapture : false, wrappedFn = null;

  if (overrideContext) {
    if (overrideContext === true) {
      context = obj;
    }
    else {
      context = overrideContext;
    }
  }
  wrappedFn = function(){
    return fn.call(context);
  };
  try {
    el.addEventListener(event, wrappedFn, isCapture);
  }
  catch (e) {
    try {
      el.attachEvent('on' + event, wrappedFn);
    }
    catch (e) {
      el['on' + event] = wrappedFn;
    }
  }
}

示例(4):再點點我,看我的‘this'是什么?

好了就這么多了,不知道對你有沒有幫助,最后說明下,本文中的部分觀點參考至《Javascript高級程序設(shè)計》(很好的一本書,推薦大家看看!),addEvent函數(shù)借鑒了YUI2.7的_addListener方法,這里也要謝謝YUI那些牛人,向他們致敬!

靜態(tài)頁訪問地址:http://img.jb51.NET/online/jsevent/event.htm(如果你也想體驗下我的“驚喜”,請用IE6訪問,點擊第一個示例鏈接,但千萬不要用Firefox,否則會掛掉,別說我沒有提醒你!!!)

JavaScript技術(shù)Javascript 事件流和事件綁定,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 我解开了岳的乳第一个女人 | 国产精品视频国产永久视频 | 蜜柚影院在线观看免费高清中文 | 91欧洲在线视精品在亚洲 | 亚洲精品自在在线观看 | 亚洲欧美综合乱码精品成人网 | 国产婷婷一区二区在线观看 | 亚洲国产在线午夜视频无 | 99热这里只有精品88 | 美女张开腿让我了一夜 | 在线日韩欧美一区二区三区 | 精品一区二区三区免费毛片 | 真实伦 乱| 日韩黄色免费 | 成人在线精品视频 | 久久精品中文字幕有码日本 | 亚洲综合色五月久久婷婷 | 女人高潮久久久叫人喷水 | 国产午夜精AV在线麻豆 | 伊人精品久久久大香线蕉99 | 精品国产国产综合精品 | 王晶三级作品 | 2021国产精品久久久久精品免费网 | 奇米色偷偷 | 超碰在线vip| 午夜影院费试看黄 | 国产哺乳期奶水avav | 久久精品热在线观看30 | 2019久久这里只精品热在线观看 | 激情内射亚州一区二区三区爱妻 | 能看的黄页最新网站 | 俄罗斯aaaa一级毛片 | 国产精品久久久精品日日 | 91精品婷婷国产综合久久8 | 十九岁韩国电影在线观看 | 色悠久久久久综合网小说 | AV无码九九久久 | 最近免费中文字幕MV免费高清 | 999视频精品全部免费观看 | 99er4久久视频精品首页 | 伊人久久大香线蕉avapp下载 |