《Javascript 高级程序设计(第三版)》笔记0x16 事件:事件流、事件处理程序

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/funkstill/article/details/85040001

目录

事件流

    事件冒泡(event bubbling)

    事件捕获(event capturing)

    DOM事件流

 事件处理程序

     HTML事件处理程序

     DOM0 级事件处理程序

     DOM2 级事件处理程序

     IE事件处理程序

     跨浏览器的事件处理程序


        JavaScript 与 HTML 之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。可以使用侦听器(或处理程序)来预订事件,以便事件发生时执行相应的代码。这种在传统软件工程中被称为观察员模式的模型,支持页面的行为(JavaScript 代码)与页面的外观(HTML 和 CSS 代码)之间的松散耦合。

事件流

       事件流描述的是从页面中接收事件的顺序。 

    事件冒泡(event bubbling)

        即事件开始时由最具体的元素(文档中嵌套层次最深的节点)接收,然后逐级向上传播到较为不具体的节点(文档)。 

<!DOCTYPE html>
<html>
	<head>
		<title>Event Bubbling Example</title>
	</head>
	<body>
		<div id="myDiv">Click Me</div>
	</body>
</html>

    事件捕获(event capturing)

        事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。

    DOM事件流

        “DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。 

 事件处理程序

        事件就是用户或浏览器自身执行的某种动作。诸如 click、 load 和 mouseover,都是事件的名字。而响应某个事件的函数就叫做事件处理程序(或事件侦听器)。事件处理程序的名字以"on"开头,因此click事件的事件处理程序就是onclick,load 事件的事件处理程序就是 onload。

     HTML事件处理程序

<input type="button" value="Click Me" onclick="alert(&quot;Clicked&quot;)" />
<script type="text/javascript">
	function showMessage(){
		alert("Hello world!");
	}
</script>
<input type="button" value="Click Me" onclick="showMessage()" />

        这样指定事件处理程序具有一些独到之处。首先,这样会创建一个封装着元素属性值的函数。这个函数中有一个局部变量 event,也就是事件对象

<!-- 输出 "click" -->
<input type="button" value="Click Me" onclick="alert(event.type)">

        通过 event 变量,可以直接访问事件对象,你不用自己定义它,也不用从函数的参数列表中读取。  

<!-- 输出 "Click Me" -->
<input type="button" value="Click Me" onclick="alert(this.value)">

         使用 with 扩展作用域

function(){
	with(document){
		with(this){
			//元素属性值
		}
	}
}
<!-- 输出 "Click Me" -->
<input type="button" value="Click Me" onclick="alert(value)">

 如果当前元素是一个表单输入元素,则作用域中还会包含访问表单元素(父元素)的入口

function(){
	with(document){
		with(this.form){
			with(this){
				//元素属性值
			}
		}
	}
}
<form method="post">
	<input type="text" name="username" value="">
	<input type="button" value="Echo Username" onclick="alert(username.value)">
</form>

        在 HTML 中指定事件处理程序有两个缺点。首先,存在一个时差问题。因为用户可能会在HTML 元素一出现在页面上就触发相应的事件,但当时的事件处理程序有可能尚不具备执行条件。另一个缺点是,这样扩展事件处理程序的作用域链在不同浏览器中会导致不同结果。不同 JavaScript引擎遵循的标识符解析规则略有差异,很可能会在访问非限定对象成员时出错。

<input type="button" value="Click Me" onclick="try{showMessage();}catch(ex){}">

     DOM0 级事件处理程序

        每个元素(包括 window 和 document)都有自己的事件处理程序属性,这些属性通常全部小写

var btn = document.getElementById("myBtn");
	btn.onclick = function(){
	alert("Clicked");
};

        使用 DOM0 级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的 this 引用当前元素。

var btn = document.getElementById("myBtn");
	btn.onclick = function(){
	alert(this.id); //"myBtn"
};

btn.onclick = null; //删除事件处理程序

     DOM2 级事件处理程序

        “DOM2 级事件” 定义了两个方法,用于处理指定和删除事件处理程序的操作: addEventListener()和removeEventListener()。所有 DOM 节点中都包含这两个方法,并且它们都接受 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
	alert(this.id);
}, false);

        使用 DOM2 级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
	alert(this.id);
}, false);
btn.addEventListener("click", function(){
	alert("Hello world!");
}, false);

        通过 addEventListener()添加的事件处理程序只能使用 removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。

var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
	alert(this.id);
}, false);
//这里省略了其他代码
btn.removeEventListener("click", function(){ //没有用!
	alert(this.id);
}, false);

var btn = document.getElementById("myBtn");
var handler = function(){
	alert(this.id);
};
btn.addEventListener("click", handler, false);
//这里省略了其他代码
btn.removeEventListener("click", handler, false); //有效!

     IE事件处理程序

        IE 实现了与 DOM 中类似的两个方法: attachEvent()和 detachEvent()。这两个方法接受相同的两个参数:事件处理程序名称与事件处理程序函数。由于 IE8 及更早版本只支持事件冒泡,所以通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
	alert("Clicked");
});

        在 IE 中使用 attachEvent()与使用 DOM0 级方法的主要区别在于事件处理程序的作用域。在使用 DOM0 级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用 attachEvent()方法的情况下,事件处理程序会在全局作用域中运行,因此 this 等于 window。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
	alert(this === window); //true
});

        attachEvent()方法也可以用来为一个元素添加多个事件处理程序。不过,与 DOM方法不同的是,这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。单击这个例子中的按钮,首先看到的是"Hello world!",然后才是"Clicked"。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
	alert("Clicked");
});
btn.attachEvent("onclick", function(){
	alert("Hello world!");
});

        使用 attachEvent()添加的事件可以通过 detachEvent()来移除,条件是必须提供相同的参数。与 DOM 方法一样,这也意味着添加的匿名函数将不能被移除。不过,只要能够将对相同函数的引用传给 detachEvent(),就可以移除相应的事件处理程序。

var btn = document.getElementById("myBtn");
var handler = function(){
	alert("Clicked");
};
btn.attachEvent("onclick", handler);
//这里省略了其他代码
btn.detachEvent("onclick", handler);

     跨浏览器的事件处理程序

        第一个要创建的方法是 addHandler(),它的职责是视情况分别使用 DOM0 级方法、 DOM2 级方法或 IE 方法来添加事件。与 addHandler()对应的方法是 removeHandler(),它也接受相同的参数。这个方法的职责是移除之前添加的事件处理程序——无论该事件处理程序是采取什么方式添加到元素中的,如果其他方法无效,默认采用 DOM0 级方法。

var EventUtil = {
	addHandler: function(element, type, handler){
		if (element.addEventListener){
			element.addEventListener(type, handler, false);
		} else if (element.attachEvent){
			element.attachEvent("on" + type, handler);
		} else {
			element["on" + type] = handler;
		}
	},
	removeHandler: function(element, type, handler){
		if (element.removeEventListener){
			element.removeEventListener(type, handler, false);
		} else if (element.detachEvent){
			element.detachEvent("on" + type, handler);
		} else {
			element["on" + type] = null;
		}
	}
};


var btn = document.getElementById("myBtn");
var handler = function(){
alert("Clicked");
};
EventUtil.addHandler(btn, "click", handler);
//这里省略了其他代码
EventUtil.removeHandler(btn, "click", handler);

猜你喜欢

转载自blog.csdn.net/funkstill/article/details/85040001