前言
本篇文章是我的讀書筆記,這里我直接從事件開始的原因是我之前沒有寫博客,最近一段時間才開始,之前的JS筆記也都有寫,如果有人想看,歡迎留言/私信,我會把之前的整理出來,
文章目錄
- 事件流
- 1.事件冒泡
- 2.事件捕獲
- 3.DOM事件流
- 事件處理程式
- 1.HTML事件處理程式
- 2.DOM0事件處理程式
- 3.DOM2事件處理程式
- 4.跨瀏覽器事件處理程式
- 事件物件
- DOM事件物件
- this、currentTarget 和 target的區別
- type屬性
- preventDefault()方法
- stopPropagation()方法
- eventPhase屬性
- 結語
JS 與 HTML 的互動是通過事件實作的
事件流
事件流就是描述接收事件的順序,
IE支持事件的冒泡流,Netscape Communicator支持事件的捕獲流,
別以為IE要停了就可以不學冒泡流了,DOM事件流是兩者的結合哦!
1.事件冒泡
事件會從開始觸發的元素逐層向上傳播,現代的瀏覽器中的事件會一直冒泡到window物件

2.事件捕獲
事件會從最不具體的節點元素傳播到最具體的節點元素,所有瀏覽器都是從window物件開始捕獲的,而DOM2Events規定是從document開始的,通常建議使用事件冒泡

3.DOM事件流
分為三個階段:事件捕獲、到達目標和事件冒泡,
事件捕獲最先發生,為提前攔截事件提供可能,然后,實際的目標元素接收到事件,最后一個階段是冒泡,最遲要在這個階段回應事件,

實際的目標在捕獲階段不會接收到事件,因為在捕獲階段從document到<html>再到<body>就結束了,下一階段再<div>元素上發生觸發事件 “到達目標" 階段,通常事件處理時被認為是冒泡階段的一部分,
現代瀏覽器都會在捕獲階段在事件目標上觸發事件,所以會有兩個機會處理事件,
事件處理程式
事件意味著用戶或瀏覽器執行的某種動作,為回應事件而呼叫的函式被稱為事件處理程式,通常函式名以"on"開頭
1.HTML事件處理程式
提前說明:這種方法使用的不多
特定元素支持的每個事件都可以使用事件處理程式的名字以HTML屬性的形式來指定,因為屬性的值是JS代碼,所以要注意轉義問題,
//具體格式如下
<input type="button" value="Click Me" onclick="console.log('Clicked')"/>
在該事件處理程式中可以呼叫在頁面其他地方定義的腳本,可以訪問全域作用域的一切,
以這種方式指定的事件處理程式,會創建一個函式來封裝屬性的值,函式有如下性質:
-
這個函式有一個特殊的區域變數
event,其保存的是event物件,函式的this值相當于事件的目標元素, -
其作用域鏈被擴展了,
document和元素自身的成員都可以被當成區域變數訪問,這是通過this實作的function() { with(document) { with(this) { //屬性值 } } } //所以事件處理程式可以直接通過屬性名訪問自己的屬性值,
但這種指定事件處理程式有一些問題:
- 時機問題,事件處理程式可能會在元素和用戶已經互動后才會運行到,即事件處理程式寫在了元素的后面,這時就會報錯,所以用此方法注意
js代碼的位置,可以用try/catch封裝 - 事件處理程式的作用域鏈的擴展在不同的瀏覽器中會有不同的結果,因為不同的
js引擎中識別符號決議規則存在差異, HTML和JS有強耦合,修改代碼比較麻煩
2.DOM0事件處理程式
這種方法使用的更多
這種方法是傳統方法,即把一個函式賦值給一個事件處理程式屬性,要使用js指定事件處理程式,必須先取得要操作物件的參考
let btn = document.getElementById("myBtn");
然后把這個屬性賦值為一個函式即可
//每個元素都有通常小寫的事件處理程式屬性
btn.onclick = function() {
console.log("Clicked");
};
注:上面的代碼在運行之后才會給事件處理程式賦值,如果在頁面中上面的代碼出現在按鈕之后,可能出現沒有反應的情況
事件處理程式會在元素的作用域中運行,即this等于元素,可以使用this參考元素本身和訪問元素的任何屬性和方法
以這種方式添加事件處理程式是注冊在事件流的冒泡階段,通過將事件處理程式屬性的值設定為null,可以移除通過DOM0方式添加的事件處理程式
3.DOM2事件處理程式
DOM2Events為事件處理程式的賦值和移除定義了兩個方法:addEventListener()和removeEventListener(),
這兩個方法的引數一致:事件名、事件處理函式和一個布林值,true表示在捕獲階段呼叫事件處理程式,false(默認)表示在冒泡階段呼叫,所有DOM節點都有這兩種方法,
//用法
let btn = document.getElementById("myBtn");
let handler = function() {
console.log(this.id);
}
btn.addEventListener("click", handler, false);
btn.removeEventListener("click", handler, false);
使用此方式的優勢可以為一個事件添加多個事件處理程式,DOM0只能添加一個,
注:使用這兩種方法時不建議添加匿名函式,因為移除事件處理程式時必須保證和添加時的引數值是一樣的,匿名函式沒有名字所以無法保證相同,就無法移除,
大多情況都會選擇將事件處理程式添加到事件流的冒泡階段,主要原因是跨瀏覽器兼容性好,放到捕獲階段通常用于攔截事件,
4.跨瀏覽器事件處理程式
由于IE不久就會停用,所以可以不考慮兼容IE
代碼如下:
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener)
element.addEventListener(type, handler,false);
else
element["on" + type] = handler;
}
removeHandler: function(element, type, handler) {
if (element.addEventListener)
element.removeEventListener(type, handler,false);
else
element["on" + type] = null;
}
};
事件物件
在DOM中發生事件時,所有相關資訊都會被收集并存盤在一個名為event的物件中,同樣不看IE,所以下面說的都是DOM事件物件,event物件在事件處理程式執行完畢后,就會被銷毀,
DOM事件物件
event物件是傳給事件處理程式的唯一引數,不管是DOM0還是DOM2都會傳入這個物件,通過HTML屬性指定的事件處理程式,同樣可以使用,
不同事件生成的事件物件會包含不同的屬性和方法,但也有一些公共的屬性和方法,如下:


this、currentTarget 和 target的區別
在事件處理程式內,this物件始終等于currentTarget,target只包含事件的實際目標,如果事件處理程式直接添加到實際的目標(比如,將點擊事件處理程式直接添加到一個按鈕上)這時這三個值都一樣的,
如果沒有添加到按鈕上,而是添加到其父級節點上,那么target就和其他兩個不一樣了,target屬性等于按鈕,但按鈕沒有注冊事件處理程式,所以事件會冒泡到其父級節點上,this和currentTarget都等于父級節點,
type屬性
type屬性在處理程式處理多個事件時很有用,比如:
let btn = document.getElementById("mybtn");
let handler = function(event) {
switch(event.type) {
case "click": //點擊事件
console.log("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;
preventDefault()方法
用于阻止特定事件的默認動作,任何可以使用此方法取消默認行為的事件,其事件物件cancelable屬性都會設定為true
let link = document.getElementById("mylink");
link.onclick = function(event) {
event.preventDefalult();
};
stopPropagation()方法
用于立即阻止事件流在DOM結構中傳播,取消后續的事件捕獲或冒泡,
let link = document.getElementById("mylink");
link.onclick = function(event) {
console.log("Clicked");
event.stopPropagation();
};
document.body.onclick = function(event) {
console.log("body clicked");
};
//Clicked
//不會輸出body clicked,因為取消了冒泡
eventPhase屬性
用于確定事件流當前所處的階段,
- 捕獲階段:1
- 目標上:2
- 冒泡階段:3
結語
事件的內容有點多,先講到這里,后面是關于事件的型別、事件的委托和模擬事件,我們下次再說~~~
閱讀的文章是《JavaScript高級程式設計(第四版)》
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/390382.html
標籤:其他
上一篇:通過案例 詳解點擊事件獲取li的index,并切換對應的圖片,排他思想,閉包,bind,let,jquery簡單應用,簡單的tab欄制作-初學者html+css+js練習demo
下一篇:vue期末復習
