原生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() 来移除,传入的参数与添加事件处理程序时相同,第二个参数(事件处理程序函数)必须是同一个(指向地址相同),所以事件处理程序函数应该保存在一个变量中,传入的是匿名函数则无法移除该事件监听器。

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