整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          帶你走進JavaScript世界系列-事件流

          帶你走進JavaScript世界系列-事件流

          avaScript 和 HTML 之間的交互是通過事件實現(xiàn)的。事件,就是文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬間。可以使用偵聽器來預定事件,以便事件發(fā)生時執(zhí)行相應的代碼。這種模式在傳統(tǒng)的軟件工程中叫做觀察者模式。

          事件流

          頁面的哪一部分會擁有某個特定的事件?設想,在一張紙上畫一組同心圓,如果把手指放在圓心上,那手指指向的不是一個圓,而是紙上的所有圓。如果你單擊了頁面上的某個按鈕,你也單擊了按鈕的容器元素,甚至單擊了整個頁面。

          事件流描述的是從頁面中接收事件的順序。但有意思的是,IE 和 Netscape 提出了完全相反的事件流概念。IE 的事件流是事件冒泡,而 Netscape 的事件流是事件捕獲。

          事件冒泡

          事件冒泡,即事件開始時由最具體的元素接收,然后逐級向上傳播到較為不具體的節(jié)點。以下面的 HTML 頁面為例:

          <!DOCTYPE html>
           <html>
           <head>
           <title>Event Bubbling Example</title>
           </head>
           <body>
           <div id="myDiv">Click Me</div>
           </body>
           </html>
          

          如果你單擊了頁面中的 div 元素,那么這個click 事件會按照如下的順序傳播:

          1. <div>
          2. <body>
          3. <html>
          4. document

          也就是說,click 事件首先在 div 元素上發(fā)生,而這個元素就是我們的單擊的元素。然后,click 事件沿 DOM 樹向上傳播,在每一個節(jié)點上都會發(fā)生,直至傳播到 document 對象。下圖展示了事件冒泡的過程:

          事件冒泡過程

          所有的瀏覽器都支持事件冒泡,但在具體實現(xiàn)上有一些差別。IE5.5 及更早版本中的事件冒泡會跳過 html 元素(從 body 直接跳到 document)。IE9、Firefox、Chrome 和 Safari 則將事件一直冒泡到 window 對象。

          事件捕獲

          事件捕獲的思想是不太具體的節(jié)點應該更早接收事件,而最具體的節(jié)點應該最后接收事件。事件捕獲的用意在于在事件到達預定目標之前捕獲它。上面的 HTML 中,如果單擊 div 元素按照事件捕獲的過程就會下列順序觸發(fā) click 事件:

          1. document
          2. html
          3. body
          4. div

          在事件捕獲過程中,document 對象首先接收到 click 事件,然后事件沿 DOM 樹依次向下,一直傳播到事件的實際目標,即 div 元素。下圖展示了事件捕獲過程:

          事件捕獲過程

          雖然事件捕獲是 Netscape 唯一支持的事件流模型,但 IE9、Safari、Chrome、Opera 和 Firefox 目前都支持這種事件流模型,這些瀏覽器都是從 window對象開始捕獲事件的。由于老版本瀏覽其不支持,因此很少有人使用事件捕獲。

          DOM 事件流

          DOM2 級事件規(guī)定的事件流包含三個階段:事件捕獲階段、處于目標階段和事件冒泡階段。首先發(fā)生的是事件捕獲,為截獲事件提供了機會。然后是事件的目標接收到事件。最后一個階段是冒泡階段,可以在這個階段對事件做出響應。還以前面的 HTML 頁面為例,單擊 div 元素會按照下圖的順序觸發(fā)事件:

          DOM 事件流過程

          在 DOM 事件流中,實際的目標 div 元素在捕獲階段不會接收事件。這意味著在捕獲階段,事件從 document 到 html 再到 body 后就停止了。下一階段是處于目標階段,于是事件在 div 上發(fā)生,并在事件處理中被看成冒泡階段的一部分。然后,冒泡階段發(fā)生,事件又傳播回文檔。多數(shù)支持 DOM 事件流的瀏覽器都實現(xiàn)流一種特定的行為;即使 DOM2 級事件規(guī)范明確要求捕獲階段不會涉及事件目標,但 IE9、Safari、Chrome、Firefox 和 Opera9.5及更高版本都會在捕獲階段觸發(fā)事件對象上的事件,結果,就有兩個機會在目標對象上面操作事件。

          JavaScript 與 HTML 之間的交互是通過事件實現(xiàn)的。事件,就是文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬間。可以使用偵聽器(或處理程序)來預定事件,以便事件發(fā)生時執(zhí)行相應的代碼。這種在傳統(tǒng)軟件工程中被稱為觀察員模式的模型,支持頁面的行為(JavaScript 代碼)與頁面的外觀(HTML 和 CSS 代碼)之間的松耦合。

          事件流

          事件流 描述的是從頁面中接收事件的順序。IE 和 Netscape 開發(fā)團隊提出了兩種實現(xiàn)事件流的方案,事件冒泡流和事件捕獲流。

          IE 提出的方案為事件冒泡流,從最具體的元素開始觸發(fā),然后向上傳播至文檔節(jié)點。

          Netscape 團隊提出的方案為事件捕獲流,事件捕獲由文檔節(jié)點開始傳播至最具體的元素。事件捕獲實際上是為在事件到達最終目標前攔截事件。

          DOM 事件流

          DOM2 Events 規(guī)范規(guī)定事件流分為 3 個階段:事件捕獲、到達目標和事件冒泡。

          1. 事件捕獲階段:事件從上往下查找對應元素,直到捕獲到事件。
          2. 到達目標階段:到達目標元素后執(zhí)行事件對應的處理函數(shù)。
          3. 事件冒泡階段:事件從目標元素開始冒泡。

          在 DOM 事件流中,實際的目標(<div>元素)在捕獲階段不會收到事件。這是因為捕獲階段從document<html>再到<body>就結束了。下一階段,即會在<div>元素上觸發(fā)事件的"到達目標"階段,通常在事件處理時被認為是冒泡階段的一部分。然后,冒泡階段開始,事件反向傳播至文檔。

          事件處理

          事件就是在瀏覽器上執(zhí)行的某種動作。如clickload等。事件處理程序(或事件監(jiān)聽器)就是響應事件而調(diào)用的函數(shù)。

          HTML事件處理程序

          可以在支持事件的HTML元素上通過屬性來指定能夠執(zhí)行的JavaScript代碼的值。如下所示:

          <input type="button" value="HTML Event Handler" onclick="alert('Click HTML Event')" />

          在 HTML 中定義的事件處理程序可以包含精確的動作指令,也可以調(diào)用在頁面其他地方定義的腳本:

          <input type="button" value="HTML Event Handler" onclick="handleHTMLEvent()" />
          <script>
              function handleHTMLEvent() {
                  alert("Click HTML Event");
              }
          </script>

          在調(diào)用handleHTMLEvent()函數(shù)之前點擊了按鈕,會發(fā)生錯誤。可以將HTML事件處理程序封裝在try/catch塊中:

          <input type="button" value="HTML Event Handler 2" onclick="try{handleHTMLEvent()} catch (e) {}" />

          這種事件處理程序會使HTML與JavaScript強耦合,不利于維護。

          DOM0事件處理程序

          通過JavaScript獲取事件處理程序并將一個函數(shù)賦值給該事件處理程序屬性。

          <input id="btn" type="button" value="DOM Event Handler" />
          <script>
              var btn=document.getElementById('btn');
              btn.onclick=function () {
                  alert("Click DOM Event");
              }
          </script>

          使用DOM0方式為事件處理程序賦值的函數(shù)被認為是元素的方法。此時獲取的this等于事件處理程序所在的元素。以這種方式添加事件處理程序注冊在事件流的冒泡階段。

          DOM2事件處理程序

          DOM2 Events 定義addEventListener()removeEventListener() 兩個方法,用于事件處理程序的賦值和移除。所有DOM節(jié)點都含這兩個方法,它們接收 3 個參數(shù):事件名、事件處理函數(shù)和一個布爾值,布爾值表示調(diào)用事件處理程序的事件流階段,true在捕獲階段,false(默認)在冒泡階段。

          <input id="btn" type="button" value="DOM Event Handler" />
          <script>
              var btn=document.getElementById('btn');
              btn.addEventListener("click", ()=> {
                  alert("DOM2 Event Handler");
              }, false);
          </script>

          使用addEventListener()可以為同一個事件添加多個事件處理程序。

          var btn=document.getElementById('btn');
          btn.addEventListener("click", ()=> {
              alert("DOM2 Event Handler");
          }, false);
          btn.addEventListener("click", ()=> {
              alert("Rep DOM2 Event Handler");
          }, false);

          使用removeEventListener()并傳入與addEventListener()同樣的參數(shù)來移除。

          var btn=document.getElementById('btn');
          btn.addEventListener("click", ()=> {
              alert("DOM2 Event Handler");
          }, false);
          btn.removeEventListener("click", function () {    // 無效果
              alert("Remove DOM2 Event Handler");
          }, false);

          但這種傳入匿名函數(shù)的事件處理程序無法移除。removeEventListener()必須和addEventListener()傳入的事件處理函數(shù)必須是同一個。

          var btn=document.getElementById('btn');
          var handler=function() {
              alert("DOM2 Event Handler");
          }
          btn.addEventListener("click", handler, false);
          btn.removeEventListener("click", handler, false);    // 有效果

          大多數(shù)情況下,事件處理程序會被添加到事件流的冒泡階段,主要原因是跨瀏覽器兼容性好。把事件處理程序注冊到捕獲階段通常用于在事件到達其指定目標之前攔截事件。如果不需要攔截,則不要使用事件捕獲。

          IE事件處理程序

          IE 實現(xiàn)了 attachEvent()detachEvent() 方法用于事件處理程序的賦值和移除。接收兩個同樣的參數(shù):事件處理程序的名字和事件處理函數(shù)。IE8以前只支持事件冒泡,使用attachEvent()會添加到冒泡階段。

          var btn=document.getElementById("btn");
          btn.attachEvent("onclick", function() {
              alert("IE Event Handler");
          });

          此時的事件處理程序是在全局作用域中運行。this等于window。也可以給一個元素添加多個事件處理程序,但事件處理程序會以添加的順序的反向觸發(fā)。

          事件對象

          DOM發(fā)生事件時會將相關信息收集并存儲在event對象中。該對象會包含一些事件的元素、類型等基本信息。

          在瀏覽器中,event對象是傳給事件處理程序的唯一參數(shù)。在添加事件處理程序時可以使用事件對象:

          <input id="btn" type="button" value="DOM Event Object" onclick="alert(event.type)">
          <script>
              var btn=document.getElementById("btn");
              btn.onclick=function(event) {
                  alert(event.type);
              };
              btn.addEventListener("click", (event)=> {
                  alert(event.type);
              }, false);
          </script>

          下表列出全部屬性和方法:

          屬性/方法

          類型

          讀/寫

          說明

          bubbles

          布爾值

          只讀

          表示事件是否冒泡

          cancelable

          布爾值

          只讀

          表示事件是否可以被取消

          currentTarget

          元素

          只讀

          當前事件處理程序所在的元素

          defaultPrevented

          布爾值

          只讀

          true表示已經(jīng)調(diào)用preventDefault()方法(DOM3 Events中新增)

          detail

          整數(shù)

          只讀

          只有UIEvent(用戶界面)事件才具有。返回一個數(shù)值,表示事件的某種信息。如click事件,detail返回的是鼠標按下的次數(shù)。

          eventPhase

          整數(shù)

          只讀

          表示事件流正被處理到了哪個階段:1代表捕獲階段,2代表到達目標,3代表冒泡階段

          target

          元素

          只讀

          事件目標

          isTrusted

          布爾值

          只讀

          true表示事件是由瀏覽器發(fā)起的。false表示事件是由腳本創(chuàng)建、修改、通過EventTarget.dispatchEvent()派發(fā)

          type

          字符串

          只讀

          被觸發(fā)的事件類型

          preventDefault()

          函數(shù)

          只讀

          用于取消事件的默認行為。只有cancelable為true才可以調(diào)用這個方法

          stopImmediatePropagation()

          函數(shù)

          只讀

          用于取消后續(xù)事件捕獲或事件冒泡,并阻止調(diào)用任何后續(xù)事件處理程序(DOM3 Events中新增)

          stopPropagation()

          函數(shù)

          只讀

          阻止捕獲和冒泡階段中當前事件的進一步傳播

          事件處理程序內(nèi)部,對于currentTargettarget兩個屬性,將事件處理程序直接添加在目標上時,this和它們是相等的。

          <body>
              <input id="btn" type="button" value="DOM Event Object" />
          </body>
          <script>
              let btn=document.getElementById("btn");
              btn.onclick=function(event) {
                  alert(event.currentTarget===this);
                  alert(event.target===this);
              };
          </script>

          如果將事件處理程序添加到按鈕的父結點上,結果就是currentTargetdocument.bodythis相等,因為它是注冊事件處理程序的元素。而target屬性等于按鈕本身,因為click事件才是真正的目標。但按鈕本身沒注冊事件處理程序,click事件冒泡到document.body,觸發(fā)注冊的處理程序。

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

          preventDefault()方法用于阻止特定事件的默認動作。比如,鏈接的默認行為就是在被單機時導航到href屬性指定的URL。如果想阻止這個導航行為,可以在onclick事件處理程序中取消,如下面的例子所示:

          let link=document.getElementById('link');
          link.onclick=function (event) {
              event.preventDefault();
          }

          任何可以通過preventDefault()取消默認行為的事件,其事件對象的cancelable屬性都會設置為true

          stopPropagation()方法用于立即阻止事件流在DOM結構中傳播,取消后續(xù)的事件捕獲或冒泡。例如,直接添加到按鈕的事件處理程序中調(diào)用stopPropagation(),可以阻止document.body上注冊事件處理程序執(zhí)行。比如:

          let btn=document.getElementById("btn");
          btn.onclick=function(event) {
              console.log("Clicked");
              event.stopPropagation();
          };
          document.body.onclick=function(event) {
              console.log("Body clicked");
          };

          IE事件對象也包含與導致其創(chuàng)建的特定事件相關的屬性和方法,很多都與DOM屬性和方法對應。如srcElement對應DOM中的targetreturnValue屬性對應DOM中的preventDefault()方法等等。

          事件類型

          DOM3 EventsDOM2 Events 基礎上重新定義了并增加了新的事件類型:

          • UI Event:用戶界面事件,涉及與 BOM 交互的通用瀏覽器事件。
          • Focus Event:焦點事件,在元素獲得和失去焦點時觸發(fā)。
          • Mouse Event:鼠標事件,使用鼠標在頁面上執(zhí)行某些操作時觸發(fā)。
          • Wheel Event:滾輪事件,使用鼠標滾輪或類似設備時觸發(fā)。
          • Input Event:輸入事件,向文檔中輸入文本時觸發(fā)。
          • Keyboard Event:鍵盤事件,使用鍵盤在頁面上執(zhí)行某些操作時觸發(fā)。
          • Composition Event:合成事件,在使用某種 IME(Input Method Editor,輸入法編輯器)輸入字符時觸發(fā)。

          用戶界面事件

          用戶界面事件或 UI 事件不一定跟用戶操作有關。這類事件在 DOM 規(guī)范出現(xiàn)之前就已經(jīng)以某種形式存在了,保留它們是為了向后兼容。UI 事件主要有以下幾種。

          • load:在 window 上當頁面加載完成后觸發(fā),在<frameset>上當所有<frame>都加載完成后觸發(fā),在<img>元素上當圖片加載完成后觸發(fā),在<object>元素上當相應對象加載完成后觸發(fā)。
          • unload:在 window 上當頁面完全卸載后觸發(fā),在<frameset>上當所有<frame>都卸載完成后觸發(fā),在<object>元素上當相應對象卸載完成后觸發(fā)。
          • abort:在<object>元素上當相應對象加載完成前被用戶提前終止下載時觸發(fā)。
          • error:在 window 上當 JavaScript 報錯時觸發(fā),在 <img> 元素上當無法加載指定圖片時觸發(fā),在 <object> 元素上當無法加載相應對象時觸發(fā),在<frameset>上當一個或多個<frame>無法完成加載時觸發(fā)。
          • select:在文本框(<input><textarea>)上當用戶選擇了一個或多個字符時觸發(fā)。
          • resize:在 window<frame>上當窗口或窗口被縮放時觸發(fā)。
          • scroll:當用戶滾動包含滾動條的元素時在元素上觸發(fā)。<body>元素包含已加載頁面的滾動條。

          大多數(shù)HTML事件與window對象和表單控件有關。

          除了DOMActivate,這些事件在DOM2 Events中都被歸為HTML Events。

          焦點事件

          當頁面中的某元素獲得(用戶選中)或失去焦點時觸發(fā)焦點事件。焦點事件有以下幾種:

          • blur:當元素失去焦點時觸發(fā)。事件不冒泡。
          • focus:當元素獲得焦點時觸發(fā)。事件不冒泡。
          • focusin:當元素獲得焦點時觸發(fā)。是focus的冒泡版事件。
          • focusout:當元素失去焦點時觸發(fā)。是blur的通用版。

          DOMFocusInDOMFocusOutfocusblur 的冒泡版,這兩個事件是Opera新增的,但已被棄用,可能還有一些瀏覽器在支持。focusinfocusout,這兩個事件是IE瀏覽器新增的,已被DOM3 Events標準化。

          焦點從頁面中一個元素轉移到另一個元素時,會依次發(fā)生如下事件:①focusout在失去焦點的元素上觸發(fā);②focusin在獲得焦點的元素上觸發(fā);③blur在失去焦點的元素上觸發(fā);④DOMFocusOut在失去焦點的元素上觸發(fā);⑤focus在獲得焦點的元素上觸發(fā);⑥DOMFocusIn在獲得焦點的元素上觸發(fā)。

          鼠標事件

          鼠標事件是較常用的事件類型,繼承 MouseEvent 接口。DOM Events 定義了 9 中鼠標事件。

          • click:用戶單擊鼠標主鍵時觸發(fā)。
          • dblclick:用戶雙擊鼠標主鍵時觸發(fā)。DOM3 Event將其標準化。
          • mousedown:用戶按下任意鼠標鍵時觸發(fā)。
          • mousemove: 用戶將鼠標在元素上移動時反復觸發(fā)。不能通過鍵盤觸發(fā)事件。
          • mouseout:用戶將鼠標從元素上移出時觸發(fā)。移動的元素可以是原始元素的外部元素,也可以是原始元素的子元素。不能通過鍵盤觸發(fā)事件。
          • mouseover:用戶將鼠標光標從元素外部移到元素內(nèi)部時觸發(fā)。不能通過鍵盤觸發(fā)。
          • mouseup:用戶釋放鼠標時觸發(fā)。不能通過鍵盤觸發(fā)。
          • mouseenter:用戶把鼠標懸停在某些元素之上時觸發(fā)。不是冒泡事件,也不會懸停在后代元素之上時觸發(fā)。DOM3 Events新增的事件。
          • mouseleave:用戶把鼠標從懸停的元素上移出時觸發(fā)。不是冒泡事件,也不會在經(jīng)過后代元素時觸發(fā)。DOM3 Events新增的事件。
          • mousewheel:滾輪事件,鼠標事件的子類別。反映鼠標滾輪或類似設備時交互。

          事件之間存在關系,取消鼠標事件的默認行為會影響其它事件。

          鍵盤事件

          鍵盤事件由用戶操作鍵盤時觸發(fā)。DOM2 Events最終沒有定義鍵盤事件,都是基于DOM0實現(xiàn)的。

          DOM3 Events 為鍵盤事件提供了規(guī)范,包含 3 個事件:

          • keydown:用戶按下鍵盤時觸發(fā)。
          • keypress:用戶按下鍵盤上某個鍵并產(chǎn)生字符時觸發(fā)。DOM3 Events 廢棄了 keypress 事件,推薦 textInput 事件。
          • keyup:用戶釋放鍵盤上按鍵時觸發(fā)。

          雖然所有元素都支持這些事件,但當用戶在文本框中輸入內(nèi)容時最容易看到。

          用戶按下鍵盤上的某個字符鍵觸發(fā)事件的正確順序如下:①keydown;②keypress;③keyupkeydownkeypress事件會在文本框出現(xiàn)變化之前觸發(fā),keyup事件在文本框出現(xiàn)變化之后觸發(fā)。非字符鍵會省略keypress事件。

          但當用戶在按下鍵足夠長的時間時,它會開始“自動重復事件”:keydownkeypress不斷被重復,直到按鍵釋放時,才會觸發(fā)keyup事件。非字符鍵會省略keypress事件步驟,不斷觸發(fā)keydown事件,直到釋放才會觸發(fā)keyup事件。

          輸入事件

          DOM3 Events 引入 textInput 輸入事件,是對 keypress 事件的擴展,用于在文本顯示給用戶之前更方便地截獲文本輸入。textInput會在文本被插入到文本框之前觸發(fā)。

          只有可編輯區(qū)域才支持 textInput 事件,如文本域,并且只有當插入字符時才觸發(fā)。該事件為 Event 對象添加了 event.data 屬性,該屬性包含新插入的字符。

          合成事件

          DOM3 Events新增合成事件,用于處理使用IME輸入時的復雜輸入序列。IME可以讓用戶輸入物理鍵盤上沒有的字符。如使用拉丁字母鍵盤的用戶可以使用IME輸入日文。IME通常需要按下多個鍵才能輸入一個字符。合成事件用于檢測和控制這種輸入。合成事件有以下 3 中:

          • compositionstart:在IME文本合成系統(tǒng)打開時觸發(fā),表示輸入即將開始。
          • compositionupdate:在新字符插入輸入字段時觸發(fā)。
          • compositionend:在IME文本合成系統(tǒng)關閉時觸發(fā),表示恢復正常鍵盤輸入。

          合成事件在很多方面與輸入事件很類似。在合成事件觸發(fā)時,事件目標是接收文本的輸入字段。唯一增加的事件屬性是 data,其中包含的值視情況而異:

          • compositionstart 事件中,包含正在編輯的文本(例如,已經(jīng)選擇了文本但還沒替換);
          • compositionupdate 事件中,包含要插入的新字符;
          • compositionend 事件中,包含本次合成過程中輸入的全部內(nèi)容。

          與文本事件類似,合成事件可以用來在必要時過濾輸入內(nèi)容。可以像下面這樣使用合成事件:

          let textbox=document.getElementById("text");
          textbox.addEventListener("compositionstart", (event)=> {
              console.log(event.data);
          });
          textbox.addEventListener("compositionupdate", (event)=> {
              console.log(event.data);
          });
          textbox.addEventListener("compositionend", (event)=> {
              console.log(event.data);
          })

          除了上述事件類型外,DOM2的變化事件(Mutation Events)被Mutation Observers取代。還有用于定義設備及設備相關的設備事件、用于觸摸設備的觸摸事件,還有資源事件等等,就不一一列舉了。

          自定義事件

          DOM3增加了自定義事件的類型。自定義事件不會觸發(fā)原生DOM事件,但可以創(chuàng)建全新的事件類型,使用document.createEvent(type)創(chuàng)建事件類型,type是一個字符串,表示創(chuàng)建的事件類型。如"UIEvents""MouseEvents"等。創(chuàng)建自定義事件,就需要傳入"CustomEvent"

          創(chuàng)建事件后,需要調(diào)用initCustomEvent()對事件進行初始化,該方法接收 4 個參數(shù)。

          • type:表示要觸發(fā)的事件類型,返回字符串,如 "customEvent"
          • bubbles:表示事件是否冒泡,返回布爾值。
          • cancelable:表示事件是否可以取消,返回布爾值。
          • detail:表示任意值,作為event對象的detail屬性。返回對象。

          自定義事件可以像其它事件一樣在DOM中派發(fā)。如:

          <div id="div" value="Dom Custom Event Handler">DOM Custom Event Handler</div>
          <script>
              let div=document.getElementById("div");
              div.addEventListener("cusEvent", (event)=> {
                  console.log("DIV: " + event.detail);
              });
              document.addEventListener("cusEvent", (event)=> {
                  console.log("DOCUMENT: " + event.detail);
              });
              let event=document.createEvent("CustomEvent");
              event.initCustomEvent("cusEvent", true, false, "Custom Event");
              div.dispatchEvent(event);
          </script>

          initCustomEvent第二個參數(shù)設置了可以冒泡,因此瀏覽器會負責把事件冒泡到document

          DOM4添加了對CustomEvent構造函數(shù)的支持,可以使用new CustomEvent(type, eventInitDict)來創(chuàng)建自定義事件。它有以下參數(shù)。

          • type:事件的類型,是一個字符串。
          • eventInitDict:一個對象,提供了事件的配置信息。

          eventInitDict參數(shù)的類型是CustomEventInit,它有幾個參數(shù)。

          • bubbles:一個布爾值,表示該事件是否會冒泡。
          • cancelable:一個布爾值,表示該事件是否可以被取消。
          • detail:當事件初始化時傳遞的數(shù)據(jù)。

          舉一個例子:

          <div id="div" value="Dom Custom Event Handler">DOM Custom Event Handler</div>
          <script>
              let div=document.getElementById("div");
              div.addEventListener("cusEvent", (event)=> {
                  console.log("DIV: " + event.detail);
              });
              document.addEventListener("cusEvent", (event)=> {
                  console.log("DOCUMENT: " + event.detail);
              });
              let event=new CustomEvent("cusEvent", {detail: {name: "大衛(wèi)"}, bubbles: true});
              div.dispatchEvent(event);
          </script>

          事件委托

          事件委托利用事件冒泡,使用一個事件處理程序來管理同一類型的事件。

          <ul id="links">
              <li id="red">Red</li>
              <li id="green">Green</li>
              <li id="blue">Blue</li>
          </ul>

          通常給<li>元素添加點擊事件,通常給三個<li>元素分配三個onclick處理程序。與其如此,我們可以在<ul>元素上添加一個事件處理程序捕獲所有的<li>元素的點擊事件:

          let list=document.getElementById('links');
          list.addEventListener("click", (event)=> {
              let target=event.target;
          
              switch (target.id) {
                  case "red":
                      document.title="大紅大紫";
                      break;
          
                  case "green":
                      location.href="http://www.sample.com";
                      break;
          
                  case "blue":
                      alert("Hi, Blue");
                      break;
              }
          });

          這樣,點擊每個<li>元素,都會將事件向上冒泡,交給父節(jié)點<ul>的事件處理程序來處理,在<ul>的事件中,通過event.targetid屬性可以確定哪個元素被點擊,然后執(zhí)行相應操作。

          事件委托具有如下優(yōu)點:

          • document對象隨時可用,任何時候都可以給它添加事件處理程序。這意味著只要頁面渲染出可點擊的元素,就可以無延遲地起作用。
          • 節(jié)省花在設置頁面事件處理程序上的時間。只指定一個事件處理程序既可以節(jié)省DOM引用,也可以節(jié)省時間。
          • 減少整個頁面所需的內(nèi)存,提升整體性能。

          可以先將事件處理程序刪除,在通過innerHTML屬性來對DOM進行刪除操作,來刪除不用的事件處理程序,來提高Web應用性能。

          <div id="div">
              <input id="btn" type="button" value="Del Event Handler">
          </div>
          <script>
              let btn=document.getElementById("btn");
              btn.onclick=function () {
                  // 執(zhí)行操作
                  ...
                  btn.onclick=null;  // 刪除事件處理程序
                  document.getElementById("div").innerHTML="Processing...";
              }
          </script>

          小結

          事件是JavaScript與網(wǎng)頁交互的主要方式。、本文主要介紹了事件的接收順序,事件對象和常見的事件類型,還有一些事件類型如HTML5事件、設備事件等沒有介紹,還有一些瀏覽器也會實現(xiàn)自己專有的事件,方便擴展?jié)M足用戶的需求的功能。事件在JavaScript中非常重要,理解事件的原理對其性能也非常重要。

          Javascript的DOM中,關于事件Event對象的知識是一定要掌握的。Event對象模型主要分為兩個部分,一個是Event對象本身具有的屬性和方法,這個參照API就可以學得;另一個是在DOM節(jié)點上綁定的事件,例如click,dblclick,mouseenter等,以及事件在DOM節(jié)點中的傳播。今天我們主要就javascript中事件流的傳播過程以及不同DOM級事件處理程序進行講解。

          事件流

          事件流可以理解為事件在頁面的DOM節(jié)點之間傳播的順序,主要分為三個過程,分別是:事件捕獲階段 --> 事件目標階段 --> 事件冒泡階段,從下圖可以看出事件的傳播過程

          DOM的事件流

          • 事件捕獲

          事件捕獲的思想是頁面上最外層的節(jié)點先接收事件,然后向內(nèi)層元素逐級傳播。例如上面的例子中,事件捕獲階段的傳播順序為:window --> document --> html --> body --> table --> tbody --> tr --> td

          • 事件冒泡

          事件冒泡和事件捕獲剛好相反,它的思想是讓最內(nèi)層節(jié)點先接收事件,然后向外層逐級傳播。上面的例子中,事件冒泡階段傳播順序為:td --> tr --> tbody --> table --> body --> html --> document --> window

          • 事件目標階段

          不管在事件傳播階段還是在事件冒泡階段,都必然經(jīng)歷事件目標階段,表示對DOM節(jié)點的事件進行處理

          事件處理程序

          事件處理程序實際上就是綁定在DOM節(jié)點上的事件函數(shù)。在W3C標準中,分為DOM0,DOM2和DOM3,而在DOM1中沒有定義事件相關內(nèi)容,因此沒有DOM1級事件模型。

          DOM0級事件模型

          通過將函數(shù)直接賦值給事件處理屬性,在DOM0中只支持事件冒泡的過程

          DOM0事件處理程序

          DOM2級事件處理程序

          在DOM2中,事件處理過程會通過不同的參數(shù)配置來決定是采用事件捕獲還是事件冒泡,還是兩個過程都執(zhí)行。由于瀏覽器的不同,DOM2中事件綁定方法也不一樣

          • IE瀏覽器

          在IE10及以下版本的瀏覽器中,只支持事件冒泡,而在IE11中又添加了對事件捕獲的支持。在IE10及以下版本中,通過下列方法添加或刪除事件

          IE10以下事件處理程序

          • 非IE瀏覽器

          非IE的事件處理程序

          通過useCapture參數(shù)來確定采用哪種方式,true表示事件捕獲,false表示事件冒泡,默認狀態(tài)為false。

          IE和非IE瀏覽器的比較

          • 相同點

          (1)支持同一個元素上綁定多個事件處理函數(shù)

          多個事件處理函數(shù)

          (2)不能刪除匿名函數(shù),刪除時必須和綁定的函數(shù)一致

          不能刪除匿名函數(shù)

          • 不同點

          (1)在使用attachEvent方法為同一個事件添加多個函數(shù)時,執(zhí)行順序與綁定的順序相反

          attachEvent綁定事件

          (2)attachEvent執(zhí)行的作用域指向全局環(huán)境,因此this指向window;而addEventListener執(zhí)行的作用域在DOM元素內(nèi)部,因此this指向綁定的元素

          • 兼容性處理

          兼容性處理

          DOM3級事件處理程序

          DOM3在保留了DOM2特性的基礎上,添加了一些新方法。最大的改進就是DOM3允許自定義事件,通過createEvent()方法完成,返回的方法通過initCustomEvent()方法來初始化。

          DOM3自定義事件

          上述例子表示,創(chuàng)建一個冒泡事件'myEvent',然后綁定在div和document上,因為采用事件冒泡,因此會先alert出‘div myEvent’,再輸出‘document myEvent’。

          總結

          以上是一些關于Event的事件流和不同DOM級事件處理程序知識的介紹,希望對大家有用。

          如果喜歡的話,記得關注小編噢,小編后續(xù)會堅持出更多技術性的文章,如果有任何問題,也歡迎提問,小編都會盡力解答的。


          主站蜘蛛池模板: 国产成人高清亚洲一区久久| 国产精品一区二区四区| 色系一区二区三区四区五区| 成人一区二区三区视频在线观看| 无码一区二区三区在线| 久久蜜桃精品一区二区三区| 国产成人无码AV一区二区 | 国产情侣一区二区三区| 国产一区二区在线观看麻豆| 91视频一区二区| 亚洲AV无码一区二区三区性色| 国产一区二区三区在线观看影院| 中文日韩字幕一区在线观看| 精品视频在线观看一区二区 | 亚洲av区一区二区三| 午夜视频一区二区| 无码人妻一区二区三区一| 国产一区二区三区不卡观| 一区二区三区免费看| 波多野结衣中文一区| 老熟妇仑乱视频一区二区| 无码人妻精品一区二区| 中文字幕精品一区二区三区视频| 国产一区二区成人| 亚洲国产一区二区a毛片| 国产成人无码一区二区在线观看| 久久久久久免费一区二区三区| 亚洲国产综合无码一区二区二三区| 99精品国产一区二区三区2021 | 久久精品一区二区影院| 国产吧一区在线视频| 亚洲国产福利精品一区二区| 无码精品人妻一区二区三区漫画| 国产高清一区二区三区四区| 波多野结衣一区二区三区高清在线 | 波多野结衣一区在线| 国产99视频精品一区| 无码人妻精品一区二区三区东京热 | 一级特黄性色生活片一区二区| 国产精品一区二区三区高清在线| 在线电影一区二区|