DOM中的事件處理概覽與原理的全面剖析

来源:http://www.cnblogs.com/susufufu/archive/2016/08/13/5768431.html
-Advertisement-
Play Games

事件是一種非同步編程的實現方式,本質上是程式各個組成部分之間的通信,DOM支持大量的事件; 本文通過這幾點向大家詳細解析事件處理的基本原理:事件類型、事件目標、事件處理程式、事件對象、事件傳播 最後再向大家介紹Event對象; (原創文章,轉摘請註明:蘇服:http://www.cnblogs.com ...


事件是一種非同步編程的實現方式,本質上是程式各個組成部分之間的通信,DOM支持大量的事件; 本文通過這幾點向大家詳細解析事件處理的基本原理:事件類型、事件目標、事件處理程式、事件對象、事件傳播 最後再向大家介紹Event對象; (原創文章,轉摘請註明:蘇服:http://www.cnblogs.com/susufufu/p/5768431.html) 一、事件類型(event type):是一個用來說明發生了什麼類型事件的全小寫的字元串,如‘mouseover’         傳統事件類型:表單事件,Window事件,滑鼠事件,鍵盤事件,DOM事件, HTML5事件,觸摸屏和移動設備事件等,這裡是所有事件的詳細介紹:DOM事件類型詳解 二、事件目標(event target):觸發事件的對象   三、事件處理程式(或事件監聽程式)(event listener):處理或響應事件的函數。當某對象觸發某事件時,瀏覽器將自動調用在該對象上註冊的函數;         註冊事件處理程式(監聽事件):             1.作為HTML屬性註冊(只會在冒泡階段觸發)如<table id="t" onclick="modifyText();">;而某些事件類型通常直接在瀏覽器上觸發,而非任何特定文檔元素上觸發,把這些事件處理程式放在<body>標簽上,但瀏覽器會在Window對象上註冊它們,如<body onload="alert('Hello world!')">,這些事件有:                 onafterprint onfocus ononline onresize onbeforeprint onhashchange                  onpagehide onstorage onbeforeunload onload onpageshow onundo                  onblur onmessage onpopstate onunload onerror onoffline onredo                 作為HTML屬性的事件的值是JS代碼字元串,是處理函數的主體,不含{},註意:儘量不要在任何其他HTML標簽上註冊事件,它違反了HTML與JavaScript代碼相分離的原則,倘若事件函數可能還沒載入進來就點擊了事件對象元素,這會導致錯誤;             2.作為DOM元素的屬性來註冊(只會在冒泡階段觸發),此時的事件處理程式屬性的名字需加‘on’首碼,這種方式相容所有瀏覽器,唯一的缺點是只能註冊一個事件處理函數,如果定義兩次onclick屬性,後一次定義會覆蓋前一次;如:window.onload = function(){...};             3.除了IE8及之前版本外的所有瀏覽器中,DOM的事件操作(監聽和觸發),都定義在EventTarget介面。Element節點、document節點和window對象,都部署了這個介面。此外,XMLHttpRequest、AudioNode、AudioContext等瀏覽器內置對象,也部署了這個介面。該介面有三個方法,addEventListener和removeEventListener用於綁定和移除監聽函數,dispatchEvent用於觸發事件;                 addEventListener(type,listener,boolean)方法來註冊listener,第三個參數設置事件的傳播方式,通常使用預設值false,表示監聽函數只在冒泡階段(pupple)被觸發,當設為true時,表示監聽函數在捕獲階段(capture)觸發;可以為同一對象上的同一類型事件註冊任意多個listener,所有listener會按照註冊順序觸發(註冊重覆的listener將會被瀏覽器忽略);                 如果希望向監聽函數傳遞參數,可以用匿名函數包裝一下監聽函數,如elm.addEventListener('click',function(){listen('實參')},false);                 當註冊的listener是一個對函數的引用變數,就可以用removeEventLestener(type,listener,boolean)在事件目標上刪除該listener,對同一監聽事件的冒泡事件和捕獲事件需要分別刪除,兩者互不幹擾;                 var div = document.getElementById('div');                 var listener = function (event) {                       /* do something here */                 };                 div.addEventListener('click', listener, false);                 div.removeEventListener('click', listener, false);                 dispatchEvent(event)方法在當前節點上手動觸髮指定事件,從而觸發監聽函數的執行。該方法返回一個布爾值,只要有一個監聽函數調用了Event.preventDefault(),就返回false,否則為true,參數是一個Event對象的實例,該參數不能為空,且必須是一個有效的事件對象,否則報錯;                 btn.addEventListener('click', listener, false);                 var e = new Event('click');                 btn.dispatchEvent(e); //在btn上立即觸發click事件,將立即調用listener                 下麵例子根據dispatchEvent方法的返回值,判斷事件是否被取消了                 var canceled = !btn.dispatchEvent(event);                 if (canceled) { console.log('事件取消'); }                  else { console.log('事件未取消'); }}             4.IE8及之前版本僅支持attachEvent (type,listener)和detachEvent(type,listener),它們的用法和addEventListener的區別:a.參數只有兩個;b.參數type必須加'on'首碼;c.它允許對同一監聽事件進行重覆註冊,且都會被調用;d.使用attachEvent方法有個缺點,是this的值會變成 window 對象而不是觸發事件的元素;         調用順序問題:1.通過設置對象屬性或HTML屬性註冊的處理程式一直優先調用;                                     2.使用addEventListener 註冊的處理程式按照它們的註冊順序調用;                                     3.舊版IE中使用attachEvent註冊的處理程式可能按照任何順序調用。         返回值問題:1.事件處理程式的返回值只對通過屬性註冊的處理程式才有意義,通過設置對象屬性或HTML屬性註冊 事件處理程式的返回值為false,就是告訴瀏覽器不要執行這個事件相關的預設操作。當瀏覽器要跳轉到新頁面時觸發Window對象的onbeforeunload事件,若它的的返回值為字元串,則它將出現在詢問確認對話框中;                                 2.addEventListener()或attachEvent()註冊事件處理程式若要取消瀏覽器的預設操作必須調用preventDefault()方法或設置事件對象的returnValue屬性。         this指向問題:1.addEventListener方法指定的監聽函數,內部的this對象總是指向觸發事件的那個節點;                                   2.IE8及以前的attachEvent方法註冊的事件處理函數的this指向全局對象;             以下寫法的this對象都指向Element節點。                     element.onclick = print;                     element.addEventListener('click', print, false)                     element.onclick = function () {console.log(this.id);}                     <element onclick="console.log(this.id)">             以下寫法的this對象,都指向全局對象。                     element.onclick = function (){ doSomething() };                     element.setAttribute('onclick', 'doSomething()');                     <element onclick="doSomething()">                     element.attachEvent('onclick',doSomething) //IE8         記憶體問題:對如下代碼,每個迴圈中都會創建一個新的匿名函數,占用的記憶體越來越多;由於沒有保持到匿名函數的引用,它不可能被調用 removeEventListener;所以應當把第二參數listener保持為對處理事件函數的引用;                     for(i=0 ; i<els.length ; i++){                           els[i].addEventListener("click", function(e){/*do something*/}, false});                     }         通用的相容舊版IE的工具函數 確保事件處理程式的this指向事件的目標對象的工具函數addEvent function addEvent(target,type,func){     if(target.addEventListener){         target.addEventListener(type,func,false);     }else{         target.attachEvent('on'+type,function(e){   //這裡attachEvent註冊的處理函數未綁定引用,所以無法用detachEvent刪除             return func.call(target,e);         });     } } //通用的事件處理程式(因為IE8及以前版本,作為事件目標的on-屬性的處理程式需要window.event來獲得事件對象,且觸發事件的目標節點對象通過event.srcElement屬性獲得) function func(event){     var event = event||window.event;     var target = event.target || event.srcElement;     //......處理程式代碼 }   四、事件傳播(event propagation):是瀏覽器決定哪個對象觸發其事件處理程式的過程。         “DOM2級事件”規定的事件流包括三個階段:事件捕獲階段==>處於目標階段==>事件冒泡階段。首先發生的是事件捕獲階段(從外層向內層傳播),為事件傳播經過的所有節點截獲事件提供了機會。然後是實際的目標接收事件(按註冊順序執行)。最後一個階段是冒泡階段(從內層向外層冒泡)。         當容器元素及嵌套元素,即在捕獲階段又在冒泡階段調用事件處理程式時:事件按DOM事件流的順序執行事件處理程式,且當事件處於目標階段時,事件調用順序決定於綁定事件的書寫順序         如果希望事件到某個節點為止,不再傳播,有兩種方式:1.使用事件對象的event.stopPropagation()方法來阻止當前監聽函數的傳播;2.使用事件對象的event.stopImmediatePropagation()方法來阻止當前事件在其事件對象上的所有監聽函數的傳播;         事件的代理(delegation):由於事件會在冒泡階段向上傳播到父節點,因此可以把子節點的監聽函數定義在父節點上,由父節點的監聽函數統一處理多個子元素的事件;   五、事件對象(Event):事件發生以後,會生成一個事件對象,作為參數傳給監聽函數。瀏覽器原生提供一個Event對象,所有的事件都是這個對象的實例,或者說繼承了Event.prototype對象。Event對象本身就是一個構造函數,可以用來生成新的實例。                 var ev = new Event("look", {"bubbles":true, "cancelable":false});                 document.dispatchEvent(ev);         Event構造函數接受兩個參數。第一個參數是字元串,表示事件的名稱;第二個參數是一個對象,表示事件對象的配置。該參數可以有以下兩個屬性。         bubbles:布爾值,可選,預設為false,表示事件對象是否冒泡。         cancelable:布爾值,可選,預設為false,表示事件是否可以被取消。 Event對象的屬性: 1.與事件的階段有關: bubbles: 只讀屬性,返回一個布爾值,表示當前事件是否會冒泡,可根據事件是否會冒泡來調用不同的函數。 eventPhase:返回一個整數值(0,1,2,3之一),表示事件目前所處的狀態         0,事件目前沒有發生。         1,事件目前處於捕獲階段,即處於從祖先節點向目標節點的傳播過程中。該過程是從Window對象到Document節點,再到HTMLHtmlElement節點,直到目標節點的父節點為止。         2,事件到達目標節點,即target屬性指向的那個節點。         3,事件處於冒泡階段,即處於從目標節點向祖先節點的反向傳播過程中。該過程是從父節點一直到Window對象。只有bubbles屬性為true時,這個階段才可能發生   2.與事件的預設行為有關: cancelable:返回一個布爾值,表示事件是否可以取消。如果要取消某個事件,需要在這個事件上面調用preventDefault方法 defaultPrevented:返回一個布爾值,表示該事件是否調用過preventDefault方法。   3.與事件的目標節點有關: currentTarget:返回事件執行的監聽函數所綁定的那個節點。 target:返回觸發事件的那個節點。在IE6—IE8之中,該屬性的名字不是target,而是srcElement   4.與事件對象的其他信息相關: type:返回一個字元串,表示事件類型 detail:返回一個數值,表示事件的某種信息。具體含義與事件類型有關,對於滑鼠事件,表示滑鼠按鍵在某個位置按下的次數,比如對於dblclick事件,detail屬性的值總是2 timeStamp:返回一個毫秒時間戳,表示事件發生的時間。從PerformanceTiming.navigationStart開始計算,即表示距離用戶導航至該網頁的時間。如果想將這個值轉為Unix紀元時間戳,就要計算event.timeStamp + performance.timing.navigationStart isTrusted:返回一個布爾值,表示該事件是否可以信任。用處不大,不同瀏覽器的支持不一樣。   Event對象的方法: preventDefault():取消瀏覽器對當前事件的預設行為,該方法生效的前提是,事件的cancelable屬性為true,如果為false,則調用該方法沒有任何效果。 stopPropagation():終止事件在傳播過程的捕獲、目標處理或起泡階段進一步傳播。調用該方法後,該節點上處理該事件的處理程式將被調用,事件不再被分派到其他節點。註意:該方法不能阻止同一個 Document 節點上的其他事件句柄被調用,但是它可以阻止把事件分派到其他節點 stopImmediatePropagation():阻止同一個事件的其他監聽函數被調用,只要其中有一個監聽函數調用了該方法,其他的監聽函數就不會再執行了。   參考鏈接: http://javascript.ruanyifeng.com/dom/event.html#toc31 https://developer.mozilla.org/zh-CN/docs/Web/API JavaScript權威指南第六版      
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、angularJS簡介 1.什麼是 AngularJS? AngularJS 是一個 JavaScript 框架。它是一個以 JavaScript 編寫的庫。AngularJS是協助搭建單頁面工程的開源前端框架。它通過MVC模式使得開發與測試變得更容易。AngularJS 是以一個 JavaSc ...
  • 這兩天查了好多eval()的資料,結果還是很模糊,但是把自己知道的寫下來了! ...
  • Ajax 完整教程 第 1 頁 Ajax 簡介Ajax 由 HTML、JavaScript™ 技術、DHTML 和 DOM 組成,這一傑出的方法可以將笨拙的 Web 界面轉化成交互性的 Ajax 應用程式。本文的作者是一位 Ajax 專家,他演示了這些技術如何協同工作 —— 從總體概述到細節的討論 ...
  • HTML 什麼是瀏覽器什麼是伺服器? 可以顯示伺服器中的html文件。 可以讓用戶與這些文件交互。 特點: 處理請求。 必須保證二十四小時開機狀態。 請求協議:http協議: Url的組成:協議://伺服器的ip地址:埠號/請求頁面。 原來瀏覽器所做的事情是將伺服器響應回來的response進行從 ...
  • 例一 var x=10;全局變數(開闢空間)function outer(){x=20;//此處未聲明變數(未開闢空間),只給全局變數聲明瞭,此處賦值會把全局變數開闢的存儲空間的值替換掉(全局變數中的x替換成20)。function inner(){x=30;//此處未聲明變數(未開闢空間),只給全 ...
  • { "total": 16, "rows":[ { "name": "張三", "email": "[email protected]", "date": "2016-08-13" }, { "name": "李四", "email": "[email protected]", "date": " ...
  • web前端之HTML的大框架 body元素與frameset元素 對於從事html的人員來說,我們一般熟悉的框架是先聲明html ,然後在<html>標簽對里包著<head>標簽對和<body>標簽對,body元素定義文檔的主體,包含文檔的所有內容(比如文本、超鏈接、圖像、表格和列表等等)。而我們想 ...
  • 一、表單事件: 一、表單事件: input事件當<input>、<textarea>的值發生變化時觸發。此外,打開contenteditable屬性的元素,只要值發生變化,也會觸發input事件。input事件的一個特點,就是會連續觸發,比如用戶每次按下一次按鍵,就會觸發一次input事件。 inp ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...