1. 程式人生 > >關於js事件物件(DOM中的事件物件、IE中的事件物件、跨瀏覽器的事件物件)的詳解

關於js事件物件(DOM中的事件物件、IE中的事件物件、跨瀏覽器的事件物件)的詳解

在觸發DOM上的某個事件時,會產生一個事件物件event,這個物件中包含著所有與事件有關的資訊。包括導致事件的元素、事件的型別以及其他與特定事件相關的資訊。例如,滑鼠操作導致的事件物件中,會包含滑鼠位置的資訊,而鍵盤操作導致的事件物件中,會包含與按下的鍵有關的資訊。所有瀏覽器都支援event 物件,但支援方式不同。

1)DOM中的事件物件

相容DOM 的瀏覽器會將一個event 物件傳入到事件處理程式中。無論指定事件處理程式時使用什麼方法(DOM0 級或DOM2 級),都會傳入event 物件。

var btn = document.getElementById("myBtn");
    btn.onclick = function (event) {
      alert(event.type); //"click"
    };
    btn.addEventListener("click", function (event) {
      alert(event.type); //"click"
    }, false);

在事件處理程式內部,物件this 始終等於currentTarget 的值,而target 則只包含事件的實際目標。如果直接將事件處理程式指定給了目標元素,則this、currentTarget 和target 包含相同的值。

var btn = document.getElementById("myBtn");
    btn.onclick = function (event) {
      alert(event.currentTarget === this); //true
      alert(event.target === this); //true
    };

如果事件處理程式存在於按鈕的父節點中(例如document.body),那麼這些值是不相同的。

document.body.onclick = function (event) {
      alert(event.currentTarget === document.body); //true
      alert(this === document.body); //true
      alert(event.target === document.getElementById("myBtn")); //true
    };

當單擊這個例子中的按鈕時,this 和currentTarget 都等於document.body,因為事件處理程式是註冊到這個元素上的。然而,target 元素卻等於按鈕元素,因為它是click 事件真正的目標

。由於按鈕上並沒有註冊事件處理程式,結果click 事件就冒泡到了document.body,在那裡事件才得到了處理。

this 和currentTarget 指向的是事件處理程式註冊的元素;而target指向的是事件真正目標。

在需要通過一個函式處理多個事件時,可以使用type 屬性。例如:

var btn = document.getElementById("myBtn");
    var handler = function (event) {
      switch (event.type) {
        case "click":
          alert("Clicked");
          break;
        case "mouseover":
          event.target.style.backgroundColor = "red";
          break;
        case "mouseout":
          event.target.style.backgroundColor = "";
          break;
      }
    };
    btn.onclick = handler;
    btn.onmouseover = handler;
    btn.onmouseout = handler;

定義了一個名為handler 的函式,用於處理3 種事件:click、mouseover 和mouseout。當單擊按鈕時,會出現一個與前面例子中一樣的警告框。當按鈕移動到按鈕上面時,背景顏色應該會變成紅色,而當滑鼠移動出按鈕的範圍時,背景顏色應該會恢復為預設值。這裡通過檢測event.type屬性,讓函式能夠確定發生了什麼事件,並執行相應的操作。

要阻止特定事件的預設行為,可以使用preventDefault()方法。例如,連結的預設行為就是在被單擊時會導航到其href 特性指定的URL。如果你想阻止連結導航這一預設行為,那麼通過連結的onclick 事件處理程式可以取消它,如下面的例子所示。

var link = document.getElementById("myLink");
    link.onclick = function (event) {
      event.preventDefault();
    };

只有cancelable 屬性設定為true 的事件,才可以使用preventDefault()來取消其預設行為。
另外,stopPropagation()方法用於立即停止事件在DOM 層次中的傳播,即取消進一步的事件捕獲或冒泡。例如,直接新增到一個按鈕的事件處理程式可以呼叫stopPropagation(),從而避免觸發註冊在document.body 上面的事件處理程式,如下面的例子所示。

var btn = document.getElementById("myBtn");
    btn.onclick = function (event) {
      alert("Clicked");
      event.stopPropagation();
    };
    document.body.onclick = function (event) {
      alert("Body clicked");
    };

如果不呼叫stopPropagation(),就會在單擊按鈕時出現兩個警告框。可是,由於click 事件根本不會傳播到document.body,因此就不會觸發註冊在這個元素上的onclick 事件處理程式。
事件物件的eventPhase 屬性,可以用來確定事件當前正位於事件流的哪個階段。如果是在捕獲階段呼叫的事件處理程式,那麼eventPhase 等於1;如果事件處理程式處於目標物件上,則event-Phase 等於2;如果是在冒泡階段呼叫的事件處理程式,eventPhase 等於3。這裡要注意的是,儘管“處於目標”發生在冒泡階段,但eventPhase 仍然一直等於2。

var btn = document.getElementById("myBtn");
    btn.onclick = function (event) {
      alert(event.eventPhase); //2
    };
    document.body.addEventListener("click", function (event) {
      alert(event.eventPhase); //1
    }, true);
    document.body.onclick = function (event) {
      alert(event.eventPhase); //3
    };

當單擊這個例子中的按鈕時,首先執行的事件處理程式是在捕獲階段觸發的新增到document.body中的那一個,結果會彈出一個警告框顯示錶示eventPhase 的1。接著,會觸發在按鈕上註冊的事件處理程式,此時的eventPhase 值為2。最後一個被觸發的事件處理程式,是在冒泡階段執行的新增到document.body 上的那一個,顯示eventPhase 的值為3。而當eventPhase 等於2 時,this、target和currentTarget 始終都是相等的。

只有在事件處理程式執行期間,event 物件才會存在;一旦事件處理程式執行完成,event 物件就會被銷燬。

2)IE中的事件物件

與訪問DOM中的event 物件不同,要訪問IE 中的event 物件有幾種不同的方式,取決於指定事件處理程式的方法。在使用DOM0 級方法新增事件處理程式時,event 物件作為window 物件的一個屬性存在。來看下面的例子。

var btn = document.getElementById("myBtn");
    btn.onclick = function () {
      var event = window.event;
      alert(event.type); //"click"
    };

在此,我們通過window.event 取得了event 物件,並檢測了被觸發事件的型別(IE 中的type屬性與DOM中的type 屬性是相同的)。可是,如果事件處理程式是使用attachEvent()新增的,那麼就會有一個event 物件作為引數被傳入事件處理程式函式中,如下所示。

var btn = document.getElementById("myBtn");
    btn.attachEvent("onclick", function (event) {
      alert(event.type); //"click"
    });

在像這樣使用attachEvent()的情況下,也可以通過window 物件來訪問event 物件,就像使用DOM0 級方法時一樣。不過為方便起見,同一個物件也會作為引數傳遞。
如果是通過HTML特性指定的事件處理程式,那麼還可以通過一個名叫event 的變數來訪問event物件(與DOM 中的事件模型相同)。再看一個例子。

<input type="button" value="Click Me" onclick="alert(event.type)">

IE 的event 物件同樣也包含與建立它的事件相關的屬性和方法。其中很多屬性和方法都有對應的或者相關的DOM屬性和方法。與DOM的event 物件一樣,這些屬性和方法也會因為事件型別的不同而不同,但所有事件物件都會包含下表所列的屬性和方法。

因為事件處理程式的作用域是根據指定它的方式來確定的,所以不能認為this 會始終等於事件目標。故而,最好還是使用event.srcElement 比較保險。例如:

var btn = document.getElementById("myBtn");
    btn.onclick = function () {
      alert(window.event.srcElement === this); //true
    };
    btn.attachEvent("onclick", function (event) {
      alert(event.srcElement === this); //false
    });

在第一個事件處理程式中(使用DOM0 級方法指定的),srcElement 屬性等於this,但在第二個事件處理程式中,這兩者的值不相同。
如前所述,returnValue 屬性相當於DOM 中的preventDefault()方法,它們的作用都是取消給定事件的預設行為。只要將returnValue 設定為false,就可以阻止預設行為。來看下面的例子。

var link = document.getElementById("myLink");
    link.onclick = function () {
      window.event.returnValue = false;
    };

這個例子在onclick 事件處理程式中使用returnValue 達到了阻止連結預設行為的目的。與DOM不同的是,在此沒有辦法確定事件是否能被取消。
相應地,cancelBubble 屬性與DOM 中的stopPropagation()方法作用相同,都是用來停止事件冒泡的。由於IE 不支援事件捕獲,因而只能取消事件冒泡;但stopPropagatioin()可以同時取消事件捕獲和冒泡。例如:

var btn = document.getElementById("myBtn");
    btn.onclick = function () {
      alert("Clicked");
      window.event.cancelBubble = true;
    };
    document.body.onclick = function () {
      alert("Body clicked");
    };

通過在onclick 事件處理程式中將cancelBubble 設定為true,就可阻止事件通過冒泡而觸發document.body 中註冊的事件處理程式。結果,在單擊按鈕之後,只會顯示一個警告框。

3)跨瀏覽器的事件物件

雖然DOM 和IE 中的event 物件不同,但基於它們之間的相似性依舊可以拿出跨瀏覽器的方案來。IE 中event 物件的全部資訊和方法DOM 物件中都有,只不過實現方式不一樣。不過,這種對應關係讓實現兩種事件模型之間的對映非常容易。可以對前面介紹的EventUtil 物件加以增強,新增如下方法以求同存異。

var EventUtil = {
      addHandler: function (element, type, handler) {
        //省略的程式碼
      },
      getEvent: function (event) {
        return event ? event : window.event;
      },
      getTarget: function (event) {
        return event.target || event.srcElement;
      },
      preventDefault: function (event) {
        if (event.preventDefault) {
          event.preventDefault();
        } else {
          event.returnValue = false;
        }
      },
      removeHandler: function (element, type, handler) {
        //省略的程式碼
      },
      stopPropagation: function (event) {
        if (event.stopPropagation) {
          event.stopPropagation();
        } else {
          event.cancelBubble = true;
        }
      }
    };

以上程式碼顯示,我們為EventUtil 添加了4 個新方法。第一個是getEvent(),它返回對event物件的引用。考慮到IE 中事件物件的位置不同,可以使用這個方法來取得event 物件,而不必擔心指定事件處理程式的方式。在使用這個方法時,必須假設有一個事件物件傳入到事件處理程式中,而且要把該變數傳給這個方法,如下所示。

btn.onclick = function (event) {
      event = EventUtil.getEvent(event);
    };

在相容DOM 的瀏覽器中,event 變數只是簡單地傳入和返回。而在IE 中,event 引數是未定義的(undefined),因此就會返回window.event。將這一行程式碼新增到事件處理程式的開頭,就可以確保隨時都能使用event 物件,而不必擔心使用者使用的是什麼瀏覽器。

第二個方法是getTarget(),它返回事件的目標。在這個方法內部,會檢測event 物件的target屬性,如果存在則返回該屬性的值;否則,返回srcElement 屬性的值。可以像下面這樣使用這個方法。

btn.onclick = function (event) {
      event = EventUtil.getEvent(event);
      var target = EventUtil.getTarget(event);
    };

第三個方法是preventDefault(),用於取消事件的預設行為。在傳入event 物件後,這個方法會檢查是否存在preventDefault()方法,如果存在則呼叫該方法。如果preventDefault()方法不存在,則將returnValue 設定為false。下面是使用這個方法的例子。

var link = document.getElementById("myLink");
    link.onclick = function (event) {
      event = EventUtil.getEvent(event);
      EventUtil.preventDefault(event);
    };

以上程式碼可以確保在所有瀏覽器中單擊該連結都不會開啟另一個頁面。首先,使用EventUtil.getEvent()取得event 物件,然後將其傳入到EventUtil.preventDefault()以取消預設行為。第四個方法是stopPropagation(),其實現方式類似。首先嚐試使用DOM 方法阻止事件流,否則就使用cancelBubble 屬性。下面看一個例子。

var btn = document.getElementById("myBtn");
    btn.onclick = function (event) {
      alert("Clicked");
      event = EventUtil.getEvent(event);
      EventUtil.stopPropagation(event);
    };
    document.body.onclick = function (event) {
      alert("Body clicked");
    };

在此,首先使用EventUtil.getEvent()取得了event 物件,然後又將其傳入到EventUtil.stopPropagation()。別忘了由於IE 不支援事件捕獲,因此這個方法在跨瀏覽器的情況下,也只能用來阻止事件冒泡。

相關推薦

關於js事件物件DOM事件物件IE事件物件瀏覽器事件物件

在觸發DOM上的某個事件時,會產生一個事件物件event,這個物件中包含著所有與事件有關的資訊。包括導致事件的元素、事件的型別以及其他與特定事件相關的資訊。例如,滑鼠操作導致的事件物件中,會包含滑鼠位置的資訊,而鍵盤操作導致的事件物件中,會包含與按下的鍵有關的資訊。所有瀏覽器

java面向物件四種許可權private,protected,public,友好型

俗話說沒有規矩就沒有方圓,java作為一門嚴謹的面向物件的高階程式語言,自然對許可權整個重要的問題有嚴格的控制。 Java一共有四種許可權,private (私有),public(公有)。Protected(受保護)還有友好型。 在java裡,這些語句都可以修飾類中的成員變

objective-c 類和物件靜態資料成員和靜態成員函式類方法

作為初學者,相信大家都對objective-c的靜態資料成員和靜態成員函式都挺糾結的,我現在和大家分享下我對這個知識點的理解,請大家多多指點.... 如果大家學過C++,那麼都應該知道和了解靜態資料成

JavaScript語法基礎 使用JS操作網頁DOM 使用JS操作瀏覽器BOM

JavaScript 體驗JavaScript <html > <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

js事件js事件封裝函式,js瀏覽器事件處理機制

一、事件流 事件流描述的是從頁面中接受事件的順序。 IE的事件流是事件冒泡流,而Netscape的事件流是事件捕獲流 1、事件冒泡 事件冒泡,即事件最開始由最具體的元素(文件中巢狀層次最深的那個節點)接收,然後逐級向上轉播至最不具體的節點(文件)。 2、事件捕獲 事件捕獲的

python 類和物件 類屬性,類方法,靜態方法,例項屬性,例項方法

類:類是抽象的,在使用的時候通常會找到這個類的一個具體的存在,使用這個具體的存在。一個類可以找到多個物件物件: 某一個具體事物的存在,在現實世界中可以是看的到摸得著的。 可以直接使用類與物件的關係: 類就是建立物件的模板類的構成:                1.類的名稱:

C++之函式物件/偽函式Function Object

       除了自定義的函式物件,標準庫還為我們提供了一系列現成的函式物件, 比如常見的數學、邏輯運算等。例如:negate<type>(),plus<type>(),minus<type>(),multiplies<type&g

Python可迭代物件迭代器以及iter()函式的兩個用法

在Python中,有這兩個概念容易讓人混淆。第一個是可迭代物件(Iterable),第二個是迭代器(Iterator),第三個是生成器(Generator),這裡暫且不談生成器。 可迭代物件 列表、元組、字串、字典等都是可迭代物件,可以使用for迴圈遍歷出所有元素的都可以稱為可迭代物件(Iterable)。在

關於JS面向對象原型和原型鏈以及他們之間的關系及this的

它的 .proto com js面向對象 text doc 技術分享 回調函數 回調 一:原型和原型對象: 1.函數的原型prototype:函數才有prototype,prototype是一個對象,指向了當前構造函數的引用地址。 2.函數的原型對象__proto__:所有

域問題相關知識原生js和jquery兩種方法實現jsonp

syn con 加載 developer 兩種方法 ray exe 編寫 分組 1、同源策略 同源策略(Same origin policy),它是由Netscape提出的一個著名的安全策略。同源策略是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽

瀏覽器事件封裝

tar color UNC spa src eve and prevent elb var EventUtil = { // 添加事件處理程序 addHandler: function (element,type,handler) {

機器學習的概率模型和概率密度估計方法及VAE生成式模型之二作者簡介

AR aca rtu href beijing cert school start ica Brief Introduction of the AuthorChief Architect at 2Wave Technology Inc. (a startup company

機器學習的概率模型和概率密度估計方法及VAE生成式模型之一簡介

價值 新書 The aar 生成 syn TE keras 第一章 A Gentle Introduction to Probabilistic Modeling and Density Estimation in Machine LearningAndA Detailed

機器學習的概率模型和概率密度估計方法及VAE生成式模型之五第3章 之 EM算法

ado vpd dea bee OS deb -o blog Oz 機器學習中的概率模型和概率密度估計方法及VAE生成式模型詳解之五(第3章 之 EM算法)

機器學習的概率模型和概率密度估計方法及VAE生成式模型之六第3章 之 VI/VB算法

dac term http 51cto -s mage 18C watermark BE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

機器學習的概率模型和概率密度估計方法及VAE生成式模型之七第4章 之 梯度估算

.com 概率 roc 生成 詳解 time 學習 style BE ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?機器學習中的概率模型和概率密度估計方法及V

機器學習的概率模型和概率密度估計方法及VAE生成式模型之八第4章 之 AEVB和VAE

RM mes 9.png size mar evb DC 機器 DG ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

機器學習的概率模型和概率密度估計方法及VAE生成式模型之九第5章 總結

ces mark TP 生成 機器 分享 png ffffff images ? ?機器學習中的概率模型和概率密度估計方法及VAE生成式模型詳解之九(第5章 總結)

自動化監控--zabbix的Macros巨集

巨集 Zabbix支援許多在多種情況下使用的巨集。巨集是一個變數,由如下特殊語法標識: {MACRO} 根據在上下文中, 巨集解析為一個特殊的值。有效地使用巨集可以節省時間,並使Zabbix變地更加高效。 在一個的典型用途中,巨集可以用於模板中。因此,模板的觸發器可能

自動化監控--zabbix的template模板

模板概述 模板是可以方便地應用於多個主機的一組實體。而這些實體包括:items(監控項)、triggers(觸發器),graphs(圖形)、applications(應用)、screens (聚合圖形(自Zabbix 2.0起))、low-level discovery rules