摘要:事件流事件流是指從頁(yè)面接受事件的順序一般考慮兼容性問題會(huì)使用冒泡而不適用捕獲事件冒泡事件開始時(shí)由具體的元素嵌套層次最深的元素接受然后逐級(jí)向上傳播到文檔事件捕獲基本跟事件冒泡相反事件捕獲用于在于事件到達(dá)預(yù)定目標(biāo)之前捕獲他首先接收到事件然后事件
事件流
事件流是指從頁(yè)面接受事件的順序
?
事件冒泡event bubbling一般考慮兼容性問題,會(huì)使用冒泡而不適用捕獲
事件開始時(shí)由具體的元素(嵌套層次最深的元素)接受,然后逐級(jí)向上傳播到文檔document
?
事件捕獲基本跟事件冒泡相反,事件捕獲用于在于事件到達(dá)預(yù)定目標(biāo)之前捕獲他,document首先接收到事件,然后事件依次向里傳遞,一直到傳播事件的實(shí)際目標(biāo),例如這個(gè)div是我們點(diǎn)擊的那個(gè)div
?
事件捕獲用的不多
DOM2級(jí)事件,規(guī)定的事件流包括三個(gè)階段
事件捕獲階段
處于目標(biāo)階段
事件冒泡階段
?
事件處理程序 html事件處理 (不建議使用)其實(shí)每一個(gè)事件都是有這么一個(gè)階段轉(zhuǎn)換過程的
即在html中寫的事件
兩種使用方式
DOM0級(jí)事件處理程序缺點(diǎn):不方便mvc分離,代碼混亂
將一個(gè)函數(shù)賦值給一個(gè)事件處理程序?qū)傩?/p>
主動(dòng)式的事件處理
var btn = document.getElementById("myBtn"); //主動(dòng)賦值給onclick屬性 btn.onclick = function () { console.log("Clicked"); } btn.onclick = null; // 刪除事件處理程序DOM2級(jí)事件處理程序
addEventListener() 添加事件處理程序監(jiān)聽
removeEventListener() 移除事件處理程序監(jiān)聽
所有DOM節(jié)點(diǎn)中都包含這兩個(gè)方法
被動(dòng)式的事件處理
可以添加多個(gè)多個(gè)事件處理程序,他們會(huì)按照添加的順序觸發(fā)
大多數(shù)情況下,都是將時(shí)間處理程序添加到事件流的冒泡階段,這樣可以最大限度的兼容各種瀏覽器.
最好只在需要在事件到達(dá)目標(biāo)之前截獲他的時(shí)候?qū)r(shí)間處理程序添加到捕獲階段
var btn = document.getElementById("myBtn"); //三個(gè)參數(shù),要處理的事件名,作為事件處理程序的函數(shù)和一個(gè)布爾值 btn.addEventListener("click",function () { alert(this.id); //true表示捕獲階段調(diào)用事件處理程序,false表示在冒泡階段調(diào)用事件處理程序 },false)
removeEventListener只能移除添加時(shí)傳入的函數(shù),所以匿名函數(shù)是沒辦法移除的(匿名函數(shù)沒有辦法確定是同一個(gè))
var btn = document.getElementById("myBtn"); //將匿名函數(shù)改成有名函數(shù) var handler = function () { alert(this.id); }; btn.addEventListener("click",handler,false); //可以移除 btn.removeEventListener("click",handler,false);事件對(duì)象
在觸發(fā)DOM上的某個(gè)事件時(shí),會(huì)產(chǎn)生一個(gè)事件對(duì)象event,這個(gè)對(duì)象包含著所有與事件相關(guān)的信息. 事件屬性查看
var btn = document.getElementById("myBtn"); //這個(gè)event就是事件對(duì)象,里面的屬性可以直接調(diào)用查看 btn.onclick = function (event) { alert(event.type);//返回click }; btn.addEventListener("click",function (event) { alert(event.type);//返回click },false)
如果點(diǎn)擊一個(gè)在body里面的myBtn元素:
document.body.onclick = function (event) { console.log(event.currentTarget === document.body); //返回true console.log(this === document.body); //返回true console.log(event.target === document.getElementById("myBtn")); //返回true }
1.currentTarget代表事件處理程序當(dāng)前正在處理的事件的那個(gè)元素,那么本例子的話就是body,另外this也是body,因?yàn)槭录幚沓绦蚴亲?cè)到body 上的
2.target是事件的目標(biāo),即點(diǎn)擊的那個(gè)元素,就是myBtn
3.需要注意的是即使點(diǎn)擊了一個(gè)元素,但是因?yàn)樽罱K都會(huì)冒泡到body那里,所以事件處理處理會(huì)在冒泡到最外層進(jìn)行處理
通過判斷事件對(duì)象的type來觸發(fā)不同的事件處理程序,用于需要通過一個(gè)函數(shù)處理多個(gè)事件時(shí).
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;阻止特定事件的默認(rèn)行為preventDefault()
默認(rèn)行為可以使點(diǎn)擊a標(biāo)簽的時(shí)候跳轉(zhuǎn)到另外一個(gè)頁(yè)面,或者內(nèi)容超出一定大小的滾動(dòng)事件
//假設(shè)myLink是一個(gè)a標(biāo)簽 var link = document.getElementById("myLink"); link.onclick = function (event) { //阻止了url 默認(rèn)行為跳轉(zhuǎn) event.preventDefault(); };
停止事件在DOM層次中傳播,例如事件冒泡需要注意的是只有cancelable屬性設(shè)置為true的事件,才可以使用preventDefault(),這個(gè)屬性可以在瀏覽器調(diào)試模式里面看,也可以打印出來
var btn = document.getElementById("myBtn"); btn.onclick = function (event) { alert("mgBtn click"); //如果沒有屏蔽傳播的話,會(huì)出現(xiàn)兩次alert,因?yàn)槭录?huì)傳播到body,也會(huì)被觸發(fā)然后執(zhí)行 event.stopPropagation(); }; document.body.onclick = function (event) { alert("body click"); }事件對(duì)象的eventPhase屬性
用來確定事件當(dāng)前正位于事件流的哪個(gè)階段
捕獲階段調(diào)用的事件處理程序 值為1
事件處理程序處于目標(biāo)對(duì)象上 值為2
在冒泡階段調(diào)用的事件處理程序 值為3
var btn = document.getElementById("myBtn"); btn.onclick = function (event) { alert("btn:" + event.eventPhase); //返回2 }; document.body.addEventListener("click", function (event) { alert("body-1:" + event.eventPhase);//返回1 }, true); // 這里是true代表在捕獲階段 document.body.onclick = function (event) { alert("body-2:" + event.eventPhase);//返回3 }
ie事件(暫時(shí)不看) 事件類型 ui事件首先是返回1,因?yàn)槭窃诓东@階段觸發(fā),按照流程上是先捕獲然后再到目標(biāo)再到冒泡的,而捕獲階段是從最外層往里傳播的,所以是body
然后是到達(dá)了目標(biāo)myBtn,所以返回2
3.再到返回3,冒泡階段,是從最里往外傳播,最里的是myBtn,最外是body,所以觸發(fā)了最后的body事件處理程序
load
當(dāng)頁(yè)面完全加載后在window上面觸發(fā)(包括所有img,js,css等)
window.addEventListener("load",function (event) { alert("loaded"); })
在DOM2級(jí)事件規(guī)范,應(yīng)該在document而非window上面觸發(fā)load事件,但是所有瀏覽器都在window上面實(shí)現(xiàn)了該事件,所以這樣用確保兼容性
也可以多帶帶對(duì)某個(gè)元素的加載進(jìn)行觸發(fā)
var img = document.getElementById("myImg"); img.addEventListener("load",function (event) { //這個(gè)加載是指圖片完全加載完成,包括下載成功 alert(event.src); });
window.addEventListener("load", function (event) { //創(chuàng)建了img元素 var img = document.createElement("img"); //添加load事件監(jiān)聽 img.addEventListener("load", function (event) { alert("aa"); }); //輸出到dom樹 document.body.appendChild(img); //設(shè)置src后,img才會(huì)開始加載 img.src = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png"; })
img只有設(shè)置了src屬性才會(huì)開始下載
script文件的話,只有設(shè)置了src并且放到dom樹里面才會(huì)開始下載
確定js文件是否加載成功
window.addEventListener("load", function (event) { //創(chuàng)建了script元素 var script = document.createElement("script"); //添加load事件監(jiān)聽 script.addEventListener("load", function (event) { alert("Loaded"); }); //script設(shè)置src后,并且添加到dom樹后才會(huì)開始加載 script.src = "https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.js"; //輸出到dom樹 document.body.appendChild(script); })
unload
與load事件對(duì)應(yīng),這個(gè)事件在文檔被完全卸載后觸發(fā),例如用戶從一個(gè)頁(yè)面切換到另外一個(gè)頁(yè)面,一般用于清楚引用,避免內(nèi)存泄露
window.addEventListener("unload", function (event) { alert("aaa"); })
abort
在用戶停止下載過程時(shí),如果嵌入的內(nèi)容沒有加載完,則在對(duì)象元素上觸發(fā)
error
當(dāng)發(fā)生js錯(cuò)誤時(shí)在window上面觸發(fā)
當(dāng)無(wú)法加載圖像時(shí),在img觸發(fā)
如果嵌入的內(nèi)容沒有加載完,則在對(duì)象元素上觸發(fā)
select
當(dāng)用戶選擇文本框 input或texterea中的一個(gè)或多個(gè)字符時(shí)觸發(fā)
resize
調(diào)整瀏覽器窗口的高度或者寬度的時(shí)候觸發(fā)
scroll
當(dāng)用戶滾動(dòng)帶滾動(dòng)條的元素中的內(nèi)容時(shí),在該元素上觸發(fā)
blur 在元素失去焦點(diǎn)時(shí)觸發(fā)
DOMFocusIn 用下面的
DOMFocusOut 用下面的
focus 在元素獲得焦點(diǎn)時(shí)觸發(fā),這個(gè)事件不會(huì)冒泡
focusin 在元素獲得焦點(diǎn)時(shí)觸發(fā),會(huì)冒泡
focusout 在元素失去焦點(diǎn)時(shí)觸發(fā)
鼠標(biāo)事件即使focus和blur不冒泡,但是也可以在捕獲階段偵聽到
click 單擊
dblclick 雙擊
mousedown 用戶按下了鼠標(biāo)按鈕
mouseenter 鼠標(biāo)從元素外部首次移動(dòng)到元素范圍之內(nèi)
mouseleave 鼠標(biāo)從元素范圍內(nèi)移動(dòng)到元素范圍外
mousemove 鼠標(biāo)在元素內(nèi)部移動(dòng)時(shí)重復(fù)觸發(fā)
mouseout 鼠標(biāo)在元素上方
mouseover 當(dāng)鼠標(biāo)指針位于一個(gè)元素外部,然后用戶將其首次移入另外一個(gè)元素邊界之內(nèi)觸發(fā)
mouseup 用戶釋放鼠標(biāo)按鈕時(shí)觸發(fā)
觸摸設(shè)備除了mouseenter 和mouseleave,所有鼠標(biāo)事件都會(huì)冒泡
輕擊可單擊元素會(huì)觸發(fā)mousemove事件,如果此操作會(huì)導(dǎo)致內(nèi)容變化,將不再有其他事件發(fā)生,如果屏幕沒有因此變化,那么會(huì)依次發(fā)生mousedown,mouseup和click事件
輕擊不可單擊元素不會(huì)觸發(fā)任何事件
兩個(gè)手指放在屏幕上且頁(yè)面隨手指移動(dòng)而滾動(dòng)時(shí)會(huì)觸發(fā)mousewheel和scroll事件
滾輪事件mousewheel,值是event.wheelDelta,方向是用正負(fù)判斷
文本事件和鍵盤事件keydown 當(dāng)用戶按下減胖上的任意鍵時(shí)觸發(fā),而且如果按住不放的話會(huì)重復(fù)觸發(fā)
keypress 當(dāng)用戶按下鍵盤的字符鍵時(shí)觸發(fā),而且如果按住不放的話會(huì)重復(fù)觸發(fā)
keyup 當(dāng)用戶釋放鍵盤上的按鍵時(shí)觸發(fā)
首先會(huì)觸發(fā)keydown,然后keypress,然后keyup
需要知道鍵碼,對(duì)應(yīng)不同的按鍵
字符編碼(ASCII編碼),用戶按鍵后輸入的屏幕文本的顯示內(nèi)容,用charCode屬性,用String.fromCharCode()轉(zhuǎn)換為實(shí)際的字符
只有一個(gè)文本事件,textInput,用戶按下能夠輸入實(shí)際字符的鍵時(shí)才會(huì)觸發(fā)
textInput的事件的對(duì)象里面有一個(gè)屬性inputMethod,用來分辨文本輸入到文本框的方式
0 不確定是怎么輸入 1 鍵盤輸入 2 文本粘貼 3 拖放進(jìn)來的 4 IME輸入 5 通過表單中選擇某一項(xiàng)輸入 6 手寫輸入 7 語(yǔ)音輸入 8 通過幾種方式組合輸入 9 通過腳本輸入變動(dòng)事件
dom變動(dòng)的時(shí)候觸發(fā)
刪除節(jié)點(diǎn)
replaceChild的時(shí)候
插入節(jié)點(diǎn)
appendChild(),replaceChild()或insertBefor()的時(shí)候
DOMContentLoaded事件,相對(duì)于load事件會(huì)在頁(yè)面中的一切都加載完成后觸發(fā),這個(gè)的話,就只會(huì)在dom樹加載完成后觸發(fā),不理會(huì)其他img,js文件,css文件之類的
jquery的document.ready()的加載方式就是使用跟這個(gè)
pageshow和pagehide事件
在頁(yè)面顯示觸發(fā)(在load之后)和在頁(yè)面隱藏時(shí)觸發(fā)(在unload之前)
hashchange事件
url參數(shù)列表的錨點(diǎn)!!!變化的時(shí)候通知開發(fā)人員,錨點(diǎn)是#這樣的
window.addEventListener("hashchange", function (event) { console.log(event); //返回一個(gè)對(duì)象 // console.log("old url:" + event.oldURL + "new url:" + event.newURL); },false);
返回的對(duì)象里面有很多有用的信息,例如
newURL : "http://localhost:63342/test-webstorm/test5.html?_ijt=dhn30q02o026mo2upn01tav7jn#dsad" oldURL : "http://localhost:63342/test-webstorm/test5.html?_ijt=dhn30q02o026mo2upn01tav7jn"設(shè)備事件
跳過
觸摸手勢(shì)事件touchstart 當(dāng)手指觸摸屏幕時(shí)觸發(fā)
touchmove 當(dāng)手指滑動(dòng)時(shí)連續(xù)觸發(fā)
touchend 當(dāng)手指離開屏幕時(shí)觸發(fā)
touchcancel 當(dāng)系統(tǒng)停止跟中觸摸時(shí)觸發(fā)
每個(gè)觸摸事件都有一些屬性
clientX,clientY(視口),screenX,screenY(屏幕),pageX,pageY(頁(yè)面) 一些坐標(biāo)屬性
target 觸摸的dom節(jié)點(diǎn)目標(biāo)
touches 表示當(dāng)前跟蹤的觸摸操作的touch對(duì)象數(shù)組,每次觸摸都會(huì)生成一個(gè)對(duì)象數(shù)組,這個(gè)對(duì)象數(shù)組只有一個(gè)對(duì)象,所以用[0]調(diào)用
targetTouches 特定于事件目標(biāo)的touch對(duì)象的數(shù)組
changeTouches 一個(gè) TouchList 對(duì)象,包含了代表所有從上一次觸摸事件到此次事件過程中,狀態(tài)發(fā)生了改變的觸點(diǎn)的 Touch 對(duì)象,每次觸摸都會(huì)生成一個(gè)對(duì)象數(shù)組,這個(gè)對(duì)象數(shù)組只有一個(gè)對(duì)象,所以用[0]調(diào)用
function handleTouchEvent(event) { //只跟蹤一次觸摸 if (event.touches.length == 1) { switch (event.type) { case "touchstart": console.log("touch stared(" + event.touches[0].clientX + "," + event.touches[0].clientY + ")"); break; case "touchend": console.log("touch end(" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")"); break; case "touchmove": //阻止默認(rèn)滾動(dòng)行為 event.preventDefault(); console.log("touch moved(" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")"); break; } } } window.addEventListener("touchstart", handleTouchEvent); window.addEventListener("touchend", handleTouchEvent); window.addEventListener("touchmove", handleTouchEvent);內(nèi)存與性能 事件委托
解決事件處理程序過多的問題
通過添加一次事件可以綁定所有的li,利用冒泡的特性
var list = document.getElementById("myLinks"); list.addEventListener("click",function (event) { //event事件對(duì)象有target屬性,里面還有id //根據(jù)里面的不同的id來觸發(fā)不同的事件處理邏輯 //每一個(gè)li都能夠冒泡到上層的ul,所以可以得到被處理 switch (event.target.id){ case "test1": console.log("test111111"); break; case "test2": console.log("test22222"); break; } });移除事件處理程序
空事件處理程序過多也會(huì)導(dǎo)致性能不好
例如手動(dòng)設(shè)置null
btn.onclick = null;
但是沒說有對(duì)于addEventListener那種處理.
模擬事件模擬事件在測(cè)試web應(yīng)用程序時(shí)候是一種極其有用的技術(shù)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/81235.html
摘要:節(jié)點(diǎn)層次類型和屬性假設(shè)我的是一個(gè)元素返回至于就是元素的名稱節(jié)點(diǎn)關(guān)系每個(gè)節(jié)點(diǎn)都有一個(gè)屬性其中保存著一個(gè)對(duì)象是一個(gè)類數(shù)組對(duì)象這個(gè)對(duì)象有屬性但不屬于對(duì)象會(huì)隨著結(jié)構(gòu)變化而變化因?yàn)槭穷悢?shù)組所以訪問里面的屬性可以使用索引也可以使用方法效果是一樣的 節(jié)點(diǎn)層次 ?showImg(https://segmentfault.com/img/bVIl1b?w=646&h=407); node類型-dom1 ...
摘要:但是通過添加的匿名函數(shù)無(wú)法移除,最好是在其他地方定義事件處理程序的函數(shù),然后將該函數(shù)的名稱傳給第二個(gè)參數(shù)。一中的事件對(duì)象對(duì)象兼容級(jí)和級(jí)的瀏覽器將對(duì)象傳入到事件處理程序中。 一、事件流 假設(shè)有如下HTML代碼: Event Click me 其DOM樹如下圖所示:showImg(https://segmentfault.com/img/bVUUWA?w=50...
摘要:項(xiàng)目中我們可通過設(shè)置采集率,或?qū)σ?guī)定時(shí)間內(nèi)數(shù)據(jù)匯總再上報(bào),減少請(qǐng)求數(shù)量,從而緩解服務(wù)端壓力。借鑒別人的一個(gè)例子只采集上報(bào)錯(cuò)誤參考文檔高級(jí)程序設(shè)計(jì)如何優(yōu)雅處理前端異常作者以樂之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVbnuud?w=640&h=640); 錯(cuò)誤類型 即時(shí)運(yùn)行錯(cuò)誤 (代碼錯(cuò)誤) 資源加載錯(cuò)誤 常見...
摘要:最全正則表達(dá)式總結(jié)驗(yàn)證號(hào)手機(jī)號(hào)中文郵編身份證地址等是正則表達(dá)式的縮寫,作用是對(duì)字符串執(zhí)行模式匹配。學(xué)習(xí)目標(biāo)了解正則表達(dá)式語(yǔ)法在中使用正則表達(dá)式在中使 JS高級(jí)技巧 本篇是看的《JS高級(jí)程序設(shè)計(jì)》第23章《高級(jí)技巧》做的讀書分享。本篇按照書里的思路根據(jù)自己的理解和經(jīng)驗(yàn),進(jìn)行擴(kuò)展延伸,同時(shí)指出書里的一些問題。將會(huì)討論安全的類型檢測(cè)、惰性載入函數(shù)、凍結(jié)對(duì)象、定時(shí)器等話題。1. 安全的類型檢測(cè)...
摘要:一寫在前面最近重讀高級(jí)程序設(shè)計(jì),總結(jié)下來,查漏補(bǔ)缺。但這種影響是單向的修改命名參數(shù)不會(huì)改變中對(duì)應(yīng)的值。這是因?yàn)閷?duì)象的長(zhǎng)度是由傳入的參數(shù)個(gè)數(shù)決定的,不是由定義函數(shù)時(shí)的命名參數(shù)的個(gè)數(shù)決定的。實(shí)際改變會(huì)同步,改變也會(huì)同步 一、寫在前面 最近重讀《JavaScript高級(jí)程序設(shè)計(jì)》,總結(jié)下來,查漏補(bǔ)缺。 二、JS簡(jiǎn)介 2.1 JS組成 ECMAscript:以ECMA-262為基礎(chǔ)的語(yǔ)言,由...
閱讀 2743·2021-11-16 11:53
閱讀 2811·2021-07-26 23:38
閱讀 2128·2019-08-30 15:55
閱讀 1836·2019-08-30 13:21
閱讀 3747·2019-08-29 17:26
閱讀 3420·2019-08-29 13:20
閱讀 939·2019-08-29 12:20
閱讀 3262·2019-08-26 10:21