成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

js中DOM事件探究

icattlecoder / 2969人閱讀

摘要:提出的事件流是事件冒泡流,提出的事件流是事件捕獲流。事件冒泡流事件開始時,由最具體的元素文檔中嵌套層次最深的哪個節(jié)點接收,逐級上傳到最不具體的元素文檔。事件處理程序,級事件處理程序,級事件處理程序,事件處理程序。

事件

綱要

理解事件流

使用事件處理程序

不同的事件類型

javascript和html的交互是通過事件實現(xiàn)的。事件就是文檔或瀏覽器窗口發(fā)生的一些特定交互瞬間。可以使用偵聽器(事件處理程序)預定事件,以便事件發(fā)生時執(zhí)行相應的代碼。

1 事件流

瀏覽器發(fā)展到第四代時(IE4和Netscape communicator4)都認為,當你單擊某個按鈕時,在單擊這個按鈕的同時,你也單擊了包含這個按鈕的容器甚至整個頁面。就如同你用手指指向一同心圓的圓心,你指向的不單是一個圓,而是以這個圓心為圓心的所有圓。
所謂事件流,指的是頁面接收事件時的順序。IE提出的事件流是事件冒泡流,Netscape communicator提出的事件流是事件捕獲流。

1.1 事件冒泡流

事件開始時,由最具體的元素(文檔中嵌套層次最深的哪個節(jié)點)接收,逐級上傳到最不具體的元素(文檔)。



  
    
    
  

  
click me

上段代碼,按照冒泡流的說法,就是你點擊div時,沿著DOM樹,你也點擊了body,html,document。

1.2 事件捕獲流

接收事件的順序,由不太具體的節(jié)點先接收,逐級向下傳到具體的節(jié)點。其用意就是在事件到達目標之前先捕獲他。

1.3 DOM事件流

"DOM2級事件",規(guī)定事件流包括三個階段。事件捕獲階段、處于目標階段、事件冒泡階段。在事件冒泡階段對事件做出響應。單擊

元素會按下圖所示順序觸發(fā)事件。

在DOM事件流中,實際的目標(

元素)在捕獲階段不會接收到事件,這意味著在捕獲階段,事件從document到再到就停止了。下一個階段是’處于目標‘階段,于是事件在
上發(fā)生,并在事件處理中被看成是冒泡階段的一部分,然后冒泡階段發(fā)生,事件又傳播回文檔。

多數(shù)支持DOM事件流的瀏覽器都實現(xiàn)了一種特定的行為:即使"DOM2級事件"規(guī)范明確要求捕獲階段不會涉及事件目標,但IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都會在捕獲階段觸發(fā)事件對象上的事件。結(jié)果,就有兩個機會在目標對象上面操作事件。(注意,IE8及更早版本不支持DOM事件流)

下面這段程序,可以看出在捕獲階段(機會1)和冒泡階段(機會2)都在目標對象上操作(觸發(fā))了事件

運行這段程序,分別點擊紅黃綠區(qū)域,感受下DOM事件執(zhí)行的順序:(在DOM2級事件處理程序中,綁定在目標元素上的事件執(zhí)行順序是按事件的注冊先后順序執(zhí)行的,所以alert3.2在3.1之前。)



  
    
    
  

    
click me
2 事件處理程序

事件就是用戶或瀏覽器自身執(zhí)行的某種動作。如click,load,mouseover等都是事件的名字。而響應某個事件的函數(shù)叫事件處理程序。事件處理程序的名字以"on"開頭,因此click事件的事件處理程序就是onclick。為事件指定處理程序的方式有好幾種。

2.1 HTML事件處理程序

某個元素支持的每種事件,都可以使用一個與之相應 事件處理程序 同名的 HTML 特性(屬性)來指定。這個特性的值應該是能執(zhí)行的Javascript代碼。例如,要在按鈕被單擊時執(zhí)行一些Javascript:。



  
    
    
  

  
    

在HTML中指定事件處理程序有兩個缺點

缺點一 時間差,HTML加載完成,但js還未加載完成(一般情況,HTML是按注冊順序加載的),如果在showMessage()函數(shù)解析前就單擊事件,便會引發(fā)錯誤。

解決辦法:將HTML事件處理程序封裝在一個try-catch塊中


/番外篇/

try...catch 的作用是測試代碼中的錯誤。

語法:

try
{
   //在此運行代碼
   tryStatements
}
catch(err)
{
   //在此處理錯誤
  catchStatements 
}

參數(shù):

tryStatements 必選項,可能發(fā)生錯誤的代碼
catchStatements 可選項,發(fā)生tryStatements中關聯(lián)的錯誤后執(zhí)行的代碼

示例一,請點擊確定/取消









語法:

try  {  
   tryStatements}  
catch(exception){  
   catchStatements}  
finally  {  
   finallyStatements}

參數(shù):
finallyStatements:可選項,當tryStatements,catchStatements皆拋出錯誤執(zhí)行的代碼

示例二 與稍后講的跨瀏覽器處理程序比較,與if...elaeif...else比較(對這里的方法若不理解,后面會講到)










缺點二 HTML與javascript代碼緊密耦合,如果要更換事件處理程序,HTML部分和javascript部分都要修改。(另外一個缺點會在后續(xù)另篇文章解析)

2.2 DOM0級事件處理程序

通過Javascript指定事件處理程序的傳統(tǒng)方式,就是將一個函數(shù)賦值給一個事件處理程序?qū)傩?。這種為事件處理程序賦值的方法,在第四代WEB瀏覽器出現(xiàn),至今所有的瀏覽器都支持。要使用javascript指定事件處理程序,首先必須取得一個要操作的對象的引用。

每個元素(包括window document)都有自己的事件處理程序?qū)傩?,這些屬性通常全部小寫,例如onclick。如下



  
    
    
  

  

在此我們通過一個文檔對象取得一個按鈕的引用,然后為他指定了onclick事件處理程序,但要注意在這些代碼(比如這里的showmessage函數(shù)代碼)運行以前不會指定事件處理程序(指的是當你點擊按鈕時,不會執(zhí)行showmessage函數(shù)代碼,因為這些代碼有可能還沒有運行),因此如果這些代碼在頁面中位于按鈕后面,有可能在一段時間內(nèi)怎么點擊都沒有反應。

2.2.1 番外篇

很多同學或許納悶 oBtn.onclick=showMessage;oBtn.onclick=showMessage(); 區(qū)別

showMessage是一個函數(shù)名,ECMAscript中函數(shù)是一個對象,函數(shù)名則是一個指向函數(shù)對象的指針,使用不帶括號的函數(shù)名是訪問函數(shù)指針,而不是調(diào)用函數(shù)。若要調(diào)用則帶括號。

我是這樣理解的 var funName=function(){...}; 是一個函數(shù)表達式,這個函數(shù)表達式是將一個匿名函數(shù)賦值給一個變量。在JS是面向?qū)ο缶幊陶Z言,變量也是對象。



  
    
    
  

  


上例我們看出函數(shù)表達式后加()直接調(diào)用。這樣理解 var funName=function(){...}; 便是一個函數(shù)表達式,oBtn.onclick=showMessage(); 這樣便是把他看成一個函數(shù)表達式,并且直接執(zhí)行這個函數(shù),而不是DOM0級事件處理程序。這塊知識我在另一篇文章中有詳細講解 https://segmentfault.com/a/11...

2.2.2 DOM0級事件處理程序的作用域

使用DOM0級方法指定事件處理程序被認為是元素的方法(之所以稱元素的方法,是因為使用DOM0級事件處理程序必須首先獲得一個操作對象,這個操作對象也就是DOM元素)。因此這時事件處理程序是在元素的作用域中進行。那么,程序中的this引用當前元素。在事件處理程序中可以通過this訪問元素的任何屬性和方法。DOM0級事件處理程序會在事件流的冒泡階段被處理。

var oBtn=document.getElementById("btn");
oBtn.onclick=function(){
    alert(this.id)
};

2.2.3 刪除DOM0級事件處理程序

oBtn.onclick=null;

2.3 DOM2級事件處理程序

DOM2級事件處理程序定義了兩個方法:用于處理指定和刪除事件處理程序的操作,addEventListener()和removeEventListener()。所有的DOM節(jié)點都包含這兩個方法。都接收三個參數(shù):要處理的事件名,作為事件處理程序的函數(shù)和布爾值。true表示在捕獲階段調(diào)用事件處理程序,false表示在冒泡階段調(diào)用事件處理程序。使用DOM2級方法指定事件處理程序也被認為是元素的方法,事件處理程序也是在元素的作用域中運行的,也可以通過this訪問元素的任何屬性和方法。

2.3.1 DOM2級事件處理程序優(yōu)點

可以添加多個事件處理程序。并且按添加的順序觸發(fā)。

var oBtn=docunment.getElementById("myBtn");
oBtn.addEventListener("click",function(){alert(this.id)},false);
oBtn.addEventListener("click",function(){alert("hello")},false);

2.3.1 DOM2級事件處理程序的移除

通過addEventListener()添加的事件處理程序只能用removeEventListener()移除,并且傳入?yún)?shù)要與添加處理程序參數(shù)完全相同。意味著通過abbEventListener()添加的匿名函數(shù)無法被移除

為了兼容各種瀏覽器我們大多數(shù)將事件處理程序添加到事件流的冒泡階段。除非為了在事件到達目標前捕獲他,才將事件處理程序添加到捕獲階段。

2.3.2 支持的瀏覽器

IE9,F(xiàn)irefox,Safari,Chrome和Opers支持DOM2級事件處理程序。

2.4 IE事件處理程序

IE事件處理程序,指定和刪除事件處理程序方法:attachEvent()和detachEvent().接受相同的兩個參數(shù),事件處理程序名稱與事件處理程序函數(shù),(注意DOM2級第一個參數(shù)是事件名)。通過attachEvent()添加的事件處理程序都會被加到冒泡階段,是因為IE8及更早版本只支持冒泡事件流

使用attachEvent()為按鈕添加一個事件處理程序.

var bnt = document.getElementById("bnt");
btn.attachEvent("onclick",function(){alert("hello");});

IE事件處理程序與DOM0級事件處理程序主要區(qū)別:事件處理程序的作用域。使用DOM0級方法,事件處理程序是在其所屬元素內(nèi)運行;attachElent()方法時,事件處理程序是在全局作用域中運行,this值因此等于Window. 在編寫跨瀏覽器代碼時牢記這一區(qū)別(跨瀏覽器稍后會說到)

同DOM2級事件處理程序一樣,移除事件只能通過detachEvent()移除,并且傳入的參數(shù)要一樣。

2.4.1支持的瀏覽器

IE和Opera

2.5跨瀏覽器事件處理程序

回顧一下前面的幾種事件處理程序。HTML事件處理程序,DOM0級事件處理程序,DOM2級事件處理程序,IE事件處理程序。

HTML事件處理程序,適合所有瀏覽器;DOM0級,適合所有瀏覽器;DOM2級,適合IE9,F(xiàn)irefox,Safari,Chrome和Opers;IE事件處理程序,適合IE和Opera。

2.5.1 跨瀏覽器事件處理程序

為了以跨瀏覽器方式處理事件,方法一,使用能夠隔離瀏覽器差異的javascript庫。方法二,自己開發(fā)最適合的處理方法。我們這里使用的便是方法二。運用能力檢測思想。我們要保證處理事件的代碼在大多數(shù)瀏覽器下一致的運行,只需關注冒泡階段(因為所有現(xiàn)代瀏覽器都支持事件冒泡)。

在講跨瀏覽器事件處理程序之前,我們先溫習一下Object。創(chuàng)建Object實例的方式有兩種

使用NEW操作符后跟Object實例,var person = new Object(); person.name="liMing"; person.age = 29;

第二種是使用對象字面量表示法,var person = {name:"liMing",age:29};

訪問對象屬性方法也有兩種

點表示法。alert(person.name);

第二種是是方括號表示法,alert(person["name"]);//優(yōu)點,可以通過變量來訪問屬性

創(chuàng)建一個對象eventUtil,對象包含兩個方法,一個方法給元素添加事件addHeadler(),另一個方法給元素去除事件removeHeader()。方法接受三個參數(shù),要操作的元素,事件名稱,和事件處理程序函數(shù)。

var EventUtil = {
  addHandler : function (element,type,handler){
    if (element.addEventListener) {
      element.addEventListener(type,handler,false);
    }else if (element.attachEvent) {
      element.attachEvent("on"+type,handler);
    }else {
      element["on"+type]=handler;
    }
  },
  removeHandler : function(element.type,handler){
    if (element.removeEventListener) {
      element.addEventListener(type,handler,false);
    }else if (element.attachEvent) {
      element.attachEvent("on"+type,handler);
    }else {
      element["on"+type]=null;
    }
  } 
};

引用:EventUnit.addHandler(element,"click",handler);

簡析:可以將EventUnil看成使用對象字面量法創(chuàng)建的Object實例。addHandler,removeHandler看成對象的屬性。在ECMAScript中函數(shù)名本身就是變量,所以函數(shù)也可以作為值來使用,所以可以講function(evement,type,handler){}看作是屬性的值。因為ECMAScript中函數(shù)可以傳進來多個參數(shù),參數(shù)的數(shù)據(jù)類型不限制,所以這里可以傳入對象eventment,字符串type,函數(shù)/對象handler.

引用形式的簡析:
創(chuàng)建一個對象:var person = {name:"liMing"}; 也可以var person=new Object(); person.name="liMing";
那么EventUnil.addHandler(element,"click",handler)可以理解為var EventUnil.addHandler=function(){};這一函數(shù)表達式的調(diào)用。注,以上簡析均是個人理解,若不正確,希望指正。

3 事件對象

在觸發(fā)DOM上的某個事件時,會產(chǎn)生一個事件對象Event,這個對象包含著所有與事件有關的信息。所有的瀏覽器都支持Event對象,但支持的方式不同。

3.1 DOM中的事件對象

無論指定事件處理程序時使用什么方法(DOM0,DOM2),都會傳入Event對象。event對象包含與創(chuàng)建它的特定事件有關的屬性和方法,觸發(fā)的事件類型不一樣,可用的屬性和方法也不一樣,不過,所有事件都會有下表列出的成員


3.1.1 currentTarget 與 target

在事件處理程序內(nèi)部,對象this始終等于currentTarget的值,而target則只包含事件的實際目標。事件處理程序存在于按鈕的父節(jié)點中(例如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
}

該結(jié)果是由于按鈕上沒有注冊事件處理程序,點擊按鈕時,click事件冒泡到了document.body,在那里事件才得到處理。

3.1.2 type

在需要一個函數(shù)處理多個事件時,可使用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.click = handler;
btn.mouseover = handler;
btn.mouseout = handler;

3.1.3 阻止事件的默認行為 preventDefault()

取消特定事件的默認行為。例如,鏈接的默認行為就是在被單擊時會導航到href特性指定的URL,如果你想阻止鏈接導航這一默認行為,通過鏈接的onclick事件處理程序取消它。

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

3.1.4 取消進一步事件的捕獲或冒泡 stopPropagation()

在講currentTarget與target時,我們知道按鈕沒有注冊事件處理程序,click事件冒泡到了document,body上?,F(xiàn)在我們可以阻止冒泡行為了,結(jié)果避免觸發(fā)注冊在document.body上的事件處理程序

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

3.1.5 確定事件位于當前事件流那個階段eventPhase

注意,只有在事件處理程序執(zhí)行期間,event對象才會存在,一旦事件處理程序執(zhí)行完畢,event對象便會被銷毀。

3.2 IE中的事件對象

要訪問IE中的event對象有幾種不同的方式,訪問的方式取決于指定事件處理程序的方法。

使用DOM0級方法添加事件處理程序。event對象作為window對象的一個屬性存在。

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

使用IE方法添加事件處理程序,event對象作為參數(shù)傳入事件處理程序中。

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

通過HTML特性指定事件處理程序,通過一個名為event變量訪問event對象(與DOM中的事件模型相同)

3.2.1 IE中event對象的屬性和方法

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

3.2.2 事件目標
因為事件處理程序作用域是根據(jù)指定他的方式確定的,所以不能認為this始終等于事件目標。由于我的瀏覽器版本問題,書中的現(xiàn)象復現(xiàn)不了,所以用下程序代替。

  var btn = document.getElementById("myBtn");
  function showMes(event){
    var event = window.event||event;
    var ele = event.target||event.srcElement;
    alert(ele === this);
  };
  var eventUnit = {
    addHandler: function(element,type,handler){
      if (element.attachEvent) {
        element.attachEvent(type,handler)
      }else{
        element[type]=handler;
      }
    }
  };
  eventUnit.addHandler(btn,"onclick",showMes);

3.2.3 取消事件的默認行為,returnValue

returnValue屬性相當與DOM中的preventDefault()方法,只要將returnValue設置為falsae就可以阻止事件的默認行為。同樣因為瀏覽器版本問題,書中代碼修改如下:

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

3.2.4 阻止事件冒泡 cancelBubble

cancelBubble屬性與DOM中的stopPropagatioin()方法作用相同,IE不支持事件捕獲,所以只用取消事件冒泡。事件處理程序中將cancelBubble設置為true便可以阻止事件冒泡行為。

3.3 跨瀏覽器的事件對象


  
  W3School
  

本文參考javascript高級程序設計第三版

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/82346.html

相關文章

  • HTML執(zhí)行順序-一探究

    摘要:而進程是多線程的,它主要包含以下主要線程渲染線程負責渲染瀏覽器界面,解析,,構(gòu)建樹和樹,布局和繪制等。且加載解析執(zhí)行會阻止解析器往下執(zhí)行,要強調(diào)渲染和下載是不沖突的,渲染是線程在執(zhí)行,下載是下載線程在執(zhí)行,瀏覽器多線程。 了解瀏覽器線程基礎 一個頁面的呈現(xiàn)主要是由瀏覽器渲染進程實現(xiàn)的(render進程),主要作用為頁面的渲染,腳本執(zhí)行,事件處理等。而render進程是多線程的,它主要包...

    darry 評論0 收藏0
  • Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面

    摘要:首先是繪制靜態(tài)的地面。上一篇下一篇無小恐龍游戲源碼探究二讓地面動起來 文章首發(fā)于我的 GitHub 博客 目錄 Chrome 小恐龍游戲源碼探究一 -- 繪制靜態(tài)地面 Chrome 小恐龍游戲源碼探究二 -- 讓地面動起來 Chrome 小恐龍游戲源碼探究三 -- 進入街機模式 Chrome 小恐龍游戲源碼探究四 -- 隨機繪制云朵 Chrome 小恐龍游戲源碼探究五 -- 隨機繪...

    lixiang 評論0 收藏0
  • 前端錯誤監(jiān)控與收集探究

    摘要:這樣很容易造成大的損失,提前做好錯誤收集和處理,可以減少損失。 編寫代碼只是做好項目的一小部分,寫代碼難免會碰到錯誤。因此,在項目上線后,我們還需要主動對項目的錯誤進行收集,不能等用戶發(fā)現(xiàn)錯誤,再聯(lián)系我們,我們再去處理。這樣很容易造成大的損失,提前做好錯誤收集和處理,可以減少損失。 本人并沒有做過相關的工作,下面的文章只是我在學習中的一點思考和總結(jié),可能有比較多不足和錯誤的地方,希望大...

    ZoomQuiet 評論0 收藏0
  • 【Vue源碼探究二】從 $mount 講起,一起探究Vue的渲染機制

    摘要:的構(gòu)造函數(shù)將自動運行啟動函數(shù)。我在閱讀源碼的過程中,發(fā)現(xiàn)源碼余行,而和模板編譯相關的代碼,則約有行左右。這個是創(chuàng)建的方法,作為第一個參數(shù)傳入。最后會返回一個節(jié)點。這個時候?qū)①x值為這個節(jié)點,掛載完成 mount, 意思為掛載??梢岳斫鉃閷ue實例(邏輯應用),掛靠在某個dom元素(載體)上的一個過程。 一、創(chuàng)建Vue實例時的渲染過程 上一篇文章我們講到, 在創(chuàng)建一個vue實例的時候(v...

    LeanCloud 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<