原生JavaScript綁定事件監聽器的幾種方法

讀《JavaScript高級程序設計》筆記,刪除線的地方是對原書的校正,因爲書比較舊,具體方法使用時應當再查閱一下文檔。

綁定事件監聽器(事件處理程序)的方法有4種,第4種僅用於 IE8 及更低版本。

1.HTML事件處理程序(行內綁定)

具體實現:通過爲HTML元素設置相應特性。特性名爲事件監聽器的名字(on + 事件名),特性值爲能夠執行的 js 代碼。瀏覽器內部會爲我們綁定的事件處理程序創建一個封裝着元素屬性值的函數;

<div onclick="alert('觸發了點擊事件')"> 點我試試 </div>

這種方式添加的事件處理程序會在事件冒泡階段被處理;

事件對象(event)訪問方法:是瀏覽器內部創建的這個封裝函數中的一個局部變量,可以直接在事件處理程序中訪問 event 變量;

<div onclick="console.log('我是事件對象', event);"> 點我試試 </div>

事件處理程序內部的 this:在這個函數內部,this 等於事件的目標元素 綁定當前事件處理程序的元素;

<div 
	onclick="
		alert('事件冒泡到div容器');
		console.log('事件目標元素是button:',event.target===document.getElementsByTagName('button')[0]);	//true
		console.log('this 是目標元素:',this===event.target);	//false
		console.log('當前事件處理程序綁定的元素是div:',event.currentTarget === document.getElementsByTagName('div')[0]);	//true
		console.log('this 是綁定當前事件處理程序的元素:',this===event.currentTarget);	//true
	"
>
	<button type="button" onclick="alert('按鈕被點擊')" >點我試試</button>
</div>

解綁事件的方法:瀏覽器內部會將爲事件處理程序創建的函數賦值給元素上與事件處理程序同名的屬性,只要將相應屬性賦值爲 null 即可。

//以上面代碼爲例
<button 
	type="button" 
	onclick="alert('按鈕被點擊')" id="firstBtn"
>
	點我試試
</button>

<button 
	type="button" 
	onclick="
		document.getElementById('firstBtn').onclick = null;
		alert('事件已刪除');
	" 
>
	點擊該按鈕刪除前一個按鈕的點擊事件
</button>

這個內部創建的函數還有一個特點,就是它會使用 with 語法在內部擴展作用域

function(){
	with(document) {
		with(this.form) {
			with(this) {}
		}
	}
}

PS:這種事件綁定方法有幾個缺點:可能會在尚不具備執行條件的時候觸發事件(依賴的 js 文件未加載)、擴展事件處理程序的作用域鏈的效果在不同瀏覽器中可能會有差異(在訪問一些對象屬性時可能導致錯誤)、使 HTML 代碼和 JS 代碼緊密耦合。

2.DOM0 級事件處理程序(爲元素屬性賦值)

具體實現:將函數賦值給元素的事件處理程序屬性;

<button type="button" id="myBtn">點我試試</button>
<script>
	var btn = document.getElementById("myBtn");
	btn.onclick = function() {
		alert("按鈕被點擊");
	};
</script>

這種方式添加的事件處理程序會在事件冒泡階段被處理;

事件對象(event)訪問方法:event 對象可以被作爲函數第一個參數傳入,也可以直接在函數內部訪問 event 變量;

<button type="button" id="myBtn" >點我試試</button>
<script>
    var btn = document.getElementById("myBtn");
    btn.onclick = function (ev) {
        console.log("事件對象:", ev);
        console.log("事件對象:", event);
    };
</script>

事件處理程序內部的 this:因爲事件處理程序是賦值給元素的屬性,所以相當於元素的方法,那麼事件處理程序就是在元素的作用域中執行的,this 就是該元素的引用(既當前事件處理程序綁定的元素,與第一種綁定方式的 this 相同);

解綁事件的方法:將對應事件處理程序的屬性設置爲 null 即可。

3.DOM2 級事件處理程序(addEventListener() 方法)

addEventListener() 文檔
removeEventListener() 文檔
具體實現:使用 addEventListener() 方法,接受3個參數(要處理的事件名、作爲事件處理程序的函數、一個布爾值,這個布爾值爲 true 表示在事件捕獲階段調用事件處理程序,爲 false 則在事件冒泡階段調用)。有些瀏覽器不支持事件捕獲(如 IE8 及更低版本),所以謹慎綁定捕獲階段的事件監聽器。

<button type="button" id="myBtn" >點我試試</button>
<script>
    var btn = document.getElementById("myBtn");
    btn.addEventListener('click', function () {
        alert("在冒泡階段觸發了按鈕的點擊事件");
    }, false);
</script>

事件對象(event)訪問方法:event 對象可以被作爲函數第一個參數傳入,也可以直接在函數內部訪問 event 變量(與上一種綁定方法相同);

<button type="button" id="myBtn" >點我試試</button>
<script>
    var btn = document.getElementById("myBtn");
    btn.addEventListener('click', function (ev) {
        console.log("事件對象:", ev);
        console.log("事件對象:", event);
    }, false);
</script>

事件處理程序內部的 this:這裏添加的事件處理程序是在調用 addEventListener() 的元素的作用域中執行的,this 就是該元素的引用(既當前事件處理程序綁定的元素,與前兩種綁定方式的 this 相同);

解綁事件的方法:通過元素調用 removeEventListener() 來移除,傳入的參數與添加事件處理程序時相同,第二個參數(事件處理程序函數)必須是同一個(指向地址相同),所以事件處理程序函數應該保存在一個變量中,傳入的是匿名函數則無法移除該事件監聽器。

這種綁定方法的優點是可以綁定多個事件處理程序,多個事件處理程序會按照綁定順序執行。

4.IE8 及更低版本的事件處理程序

detachEvent() 文檔
具體實現:使用 attachEvent() 方法,接受2個參數(事件處理程序名稱、事件處理程序函數),通過該方法綁定的事件處理程序會在冒泡階段被執行。該方法可以綁定多個事件處理程序,但執行順序與綁定順序相反。

<div>
    <button type="button" id="myBtn">點我試試</button>
</div>
<script>
    var btn = document.getElementById('myBtn');
    btn.attachEvent('onclick', function () {
        alert("觸發了點擊事件");
    });
</script>

事件對象(event)訪問方法:event 對象可以被作爲函數第一個參數傳入,也可以直接在函數內部訪問 event 變量(與上一種綁定方法相同);

<div>
    <button type="button" id="myBtn">點我試試</button>
</div>
<script>
    var btn = document.getElementById('myBtn');
    btn.attachEvent('onclick', function (ev) {
        console.log(ev);
        console.log(event);
    });
</script>

事件處理程序內部的 this:這裏添加的事件處理程序會在全局作用域中運行,與前面的方法都不相同,這裏的 this 等於 window;

解綁事件的方法:通過元素調用 detachEvent() 來移除,傳入的參數與添加事件處理程序時相同,第二個參數(事件處理程序函數)必須是同一個(指向地址相同),所以事件處理程序函數應該保存在一個變量中,傳入的是匿名函數則無法移除該事件監聽器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章