原生JavaScript事件詳解__Java

來源:互聯網
上載者:User
原文出處: http://www.cnblogs.com/iyangyuan/p/4190773.html

  JQuery這種Write Less Do More的架構,用多了難免會對原生js眼高手低。

     小菜其實不想寫這篇部落格,貌似很初級的樣子,但是看到網路上連原生js事件綁定和解除都說不明白,還是決定科普一下了。

     首先聲明,小菜懂的也不是很多,只是把我的思路和大家分享一下。

 

DOM0事件模型

 

     事件模型在不斷髮展,早期的事件模型稱為DOM0層級。

     DOM0事件模型,所有的瀏覽器都支援。

     直接在dom對象上註冊事件名稱,就是DOM0寫法,比如:

1 document.getElementById("test").onclick = function(e){};

     意思就是註冊一個onclick事件。當然,它和這種寫法是一個意思:

1 document.getElementById("test")["onmousemove"] = function(e){};

     這沒什麼,只不過是兩種訪問js對象屬性的方法,[]的形式主要是為瞭解決屬性名稱不是合法的標識符,比如:object.123肯定報錯,但是object["123"]就避免了這個問題,與此同時,[]的寫法,也把js寫活了,用字串表示屬性名稱,可以在運行時動態綁定事件。

     言歸正傳,事件被觸發時,會預設傳入一個參數e,表示事件對象,通過e,我們可以擷取很多有用的資訊,比如點擊的座標、具體觸發該事件的dom元素等等。

     基於DOM0的事件,對於同一個dom節點而言,只能註冊一個,後邊註冊的同種事件會覆蓋之前註冊的。例如:

1 var btn = document.getElementById("test");2 3 btn.onmousemove = function(e){4   alert("ok");5 };6 7 btn["onmousemove"] = function(e){8   alert("ok1");9 };

     結果會輸出ok1。

     接下來再說說this。事件觸發時,this就是指該事件在哪個dom對象上觸發。例如:

1 var btn = document.getElementById("test");2 3 btn.onmousemove = function(e){4   alert(this.id);5 };

     結果輸出test。因為事件就是在id為test的dom節點上註冊的,事件觸發時,this當然代表這個dom節點,可以理解為事件是被這個dom節點調用的。

     所以,想解除事件就相當簡單了,只需要再註冊一次事件,把值設成null,例如:

1 var btn = document.getElementById("test");2 3 btn.onclick = function(e){4   alert("ok");5 };6 7 btn.onclick = null;

     原理就是最後註冊的事件要覆蓋之前的,最後一次註冊事件設定成null,也就解除了事件綁定。

     事情還沒結束,DOM0事件模型還涉及到直接寫在html中的事件。例如:

1 <div id="test" class="test" onclick="exec();" ></div>

     通過這種方式註冊的事件,同樣遵循覆蓋原則,同樣只能註冊一個,最後一個生效。

     區別就是,這樣註冊的事件,相當於動態調用函數(有點eval的意思),因此不會傳入event對象,同時,this指向的是window,不再是觸發事件的dom對象。

 

DOM2事件模型

 

     DOM2事件模型相對於DOM0,小菜僅僅瞭解如下兩點:

 

          ·  DOM2支援同一dom元素註冊多個同種事件。

          ·  DOM2新增了捕獲和冒泡的概念。

 

     DOM2事件通過addEventListener和removeEventListener管理,當然,這是標準。

     但IE8及其以下版本瀏覽器,自娛自樂,搞出了對應的attachEvent和detachEvent,由於小菜才疏學淺,本文不做討論。

     addEventListener當然就是註冊事件,她有三個參數,分別為:"事件名稱", "事件回調", "捕獲/冒泡"。舉個例子:

1 var btn = document.getElementById("test");2 3 btn.addEventListener("click", function(e){4   alert("ok");5 }, false);

     事件名稱就不用多說了,相比DOM0,去掉了前邊的on而已。

     事件回調也很好理解,事件觸發了總得通知你吧。回調時和DOM0一樣,也會預設傳入一個event參數,同時this是指觸發該事件的dom節點。

     最後一個參數是布爾型,true代表捕獲事件,false代表冒泡事件。其實很好理解,先來個示意圖:

 

 

     意思就是說,某個元素觸發了某個事件,最先得到通知的是window,然後是document,依次而入,直到真正觸發事件的那個元素(目標元素)為止,這個過程就是捕獲。接下來,事件會從目標元素開始起泡,再依次而出,直到window對象為止,這個過程就是冒泡。

     為什麼要這樣設計呢。這貌似是由於深厚的曆史淵源,小菜也不怎麼瞭解,就不亂說了。

     由此可以看出,捕獲事件要比冒泡事件先觸發。

     假設有這樣的html結構:

1 <div id="test" class="test">2   <div id="testInner" class="test-inner"></div>3 </div>

     然後我們在外層div上註冊兩個click事件,分別是捕獲事件和冒泡事件,代碼如下:

 1 var btn = document.getElementById("test"); 2  3 //捕獲事件 4 btn.addEventListener("click", function(e){ 5   alert("ok1"); 6 }, true); 7  8 //冒泡事件 9 btn.addEventListener("click", function(e){10   alert("ok");11 }, false);

     最後,點擊內層的div,先彈出ok1,後彈出ok。結合上邊的原理圖,外層div相當於圖中的body,內層div相當於圖中最下邊的div,證明了捕獲事件先執行,然後執行冒泡事件。

     為什麼要強調點擊內層的div呢。因為真正觸發事件的dom元素,必須是內層的,外層dom元素才有機會類比捕獲事件和冒泡事件,從原理圖上就看出了。

     如果在真正觸發事件的dom元素上註冊捕獲事件和冒泡事件呢。

     html結構同上,js代碼如下:

 1 var btnInner = document.getElementById("testInner"); 2  3 //冒泡事件 4 btnInner.addEventListener("click", function(e){ 5   alert("ok"); 6 }, false); 7  8 //捕獲事件 9 btnInner.addEventListener("click", function(e){10   alert("ok1");11 }, true);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.