国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js中DOM事件探究

icattlecoder / 2955人閱讀

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

事件

綱要

理解事件流

使用事件處理程序

不同的事件類型

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

1 事件流

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

1.1 事件冒泡流

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



  
    
    
  

  
click me

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

1.2 事件捕獲流

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

1.3 DOM事件流

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

元素會按下圖所示順序觸發事件

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

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

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

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

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



  
    
    
  

    
click me
2 事件處理程序

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

2.1 HTML事件處理程序

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



  
    
    
  

  
    

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

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

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


/番外篇/

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

語法:

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

參數:

tryStatements 必選項,可能發生錯誤的代碼
catchStatements 可選項,發生tryStatements中關聯的錯誤后執行的代碼

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









語法:

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

參數:
finallyStatements:可選項,當tryStatements,catchStatements皆拋出錯誤執行的代碼

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










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

2.2 DOM0級事件處理程序

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

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



  
    
    
  

  

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

2.2.1 番外篇

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

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

我是這樣理解的 var funName=function(){...}; 是一個函數表達式,這個函數表達式是將一個匿名函數賦值給一個變量。在JS是面向對象編程語言,變量也是對象。



  
    
    
  

  


上例我們看出函數表達式后加()直接調用。這樣理解 var funName=function(){...}; 便是一個函數表達式,oBtn.onclick=showMessage(); 這樣便是把他看成一個函數表達式,并且直接執行這個函數,而不是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節點都包含這兩個方法。都接收三個參數:要處理的事件名,作為事件處理程序的函數和布爾值。true表示在捕獲階段調用事件處理程序,false表示在冒泡階段調用事件處理程序。使用DOM2級方法指定事件處理程序也被認為是元素的方法,事件處理程序也是在元素的作用域中運行的,也可以通過this訪問元素的任何屬性和方法。

2.3.1 DOM2級事件處理程序優點

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

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()移除,并且傳入參數要與添加處理程序參數完全相同。意味著通過abbEventListener()添加的匿名函數無法被移除

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

2.3.2 支持的瀏覽器

IE9,Firefox,Safari,Chrome和Opers支持DOM2級事件處理程序。

2.4 IE事件處理程序

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

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

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

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

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

2.4.1支持的瀏覽器

IE和Opera

2.5跨瀏覽器事件處理程序

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

HTML事件處理程序,適合所有瀏覽器;DOM0級,適合所有瀏覽器;DOM2級,適合IE9,Firefox,Safari,Chrome和Opers;IE事件處理程序,適合IE和Opera。

2.5.1 跨瀏覽器事件處理程序

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

在講跨瀏覽器事件處理程序之前,我們先溫習一下Object。創建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"]);//優點,可以通過變量來訪問屬性

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

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看成使用對象字面量法創建的Object實例。addHandler,removeHandler看成對象的屬性。在ECMAScript中函數名本身就是變量,所以函數也可以作為值來使用,所以可以講function(evement,type,handler){}看作是屬性的值。因為ECMAScript中函數可以傳進來多個參數,參數的數據類型不限制,所以這里可以傳入對象eventment,字符串type,函數/對象handler.

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

3 事件對象

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

3.1 DOM中的事件對象

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


3.1.1 currentTarget 與 target

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

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

3.1.2 type

在需要一個函數處理多個事件時,可使用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上。現在我們可以阻止冒泡行為了,結果避免觸發注冊在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

注意,只有在事件處理程序執行期間,event對象才會存在,一旦事件處理程序執行完畢,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對象作為參數傳入事件處理程序中。

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 事件目標
因為事件處理程序作用域是根據指定他的方式確定的,所以不能認為this始終等于事件目標。由于我的瀏覽器版本問題,書中的現象復現不了,所以用下程序代替。

  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高級程序設計第三版

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82346.html

相關文章

  • HTML執行順序-一探究

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

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

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

    lixiang 評論0 收藏0
  • 前端錯誤監控與收集探究

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

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

    摘要:的構造函數將自動運行啟動函數。我在閱讀源碼的過程中,發現源碼余行,而和模板編譯相關的代碼,則約有行左右。這個是創建的方法,作為第一個參數傳入。最后會返回一個節點。這個時候將賦值為這個節點,掛載完成 mount, 意思為掛載。可以理解為將vue實例(邏輯應用),掛靠在某個dom元素(載體)上的一個過程。 一、創建Vue實例時的渲染過程 上一篇文章我們講到, 在創建一個vue實例的時候(v...

    LeanCloud 評論0 收藏0

發表評論

0條評論

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