####1. Javascript事件流####
事件流是指页面中对象接受事件的顺序,可以分为冒泡事件流和捕获事件流,首先提出冒泡事件流的是微软的IE浏览器,而捕获事件流则是Netscape浏览器应用的事件捕获的解决方案。
1.1 冒泡事件流 冒泡事件流指的是在浏览器中从用户对目标对象触发事件处理程序后,事件最先由目标对象接受然后逐级向上传播;
<html>
<head>
<title>Event Bubbing Example</title>
</head>
<body>
<div id="div1">Click me</div>
</body>
</html>
复制代码
当用户单击页面中的div时,首先div元素捕获到事件,然后向上传播至body->html->document
所有现代浏览器都支持冒泡事件,但是IE5以下会跳过元素,IE9+、firefox、chrome和safari则将事件一直冒泡到window对象。
1.2 事件捕获流 Netscape Communication 团队提出的另一种事件流是事件捕获,事件捕获是指,在目标对象接收到事件之前先由上层元素对象捕获到事件。
<html>
<head>
<title>Event Bubbing Example</title>
</head>
<body>
<div id="div1">Click me</div>
</body>
</html>
复制代码
事件捕获的顺序为document->html->body->div
虽然然事件捕获是Netscape唯一支持的事件流模型,但IE9+等现代浏览器也都支持事件捕获,不过他们都是从window对象开始捕获事件的。
1.3 DOM事件流 “DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。当用户执行页面交互时首先发生的是事件捕获,之后是处于目标阶段,之后是冒泡阶段。
根据上图所示DOM2级事件流模型规定在捕获阶段不会设计事件目标,但是IE9+等现代浏览器都会在捕获阶段触发事件对象上的事件。
####2. 事件处理程序####
像click、load、mouseover等为事件,而绑定在事件上的函数就为事件处理程序
2.1 HTML事件处理程序
HTML事件处理程序即是指,直接在HTML代码中指定事件及事件处理函数
<input type="button" value = "Click ME" onclick = "alert('clicked')" />
复制代码
上面的例子中当点击button时则会弹出cliked
<script type="text/javascript">
function showMessage(){
alert("Hello World");
}
<script>
<input type="button" value="Click Me" onclick = "showMessage()" />
复制代码
除了直接执行语句外也可以调用页面中其他位置定义的函数,但是注意如果函数的<script>
标签位于事件绑定元素的下面则在<script>
加载未完成之前点击按钮将发生错误,因此常将HTML中的事件处理程序封装在try()catch{}块中。
<input type="button" value="click me" onclick = "try{showMessage();}catch(e){}">
复制代码
html事件处理程序中的作用域为全局作用域
2.2 DOM0级事件处理程序
DOM0级事件处理程序是指在javascript代码中首先获取目标对象然后将函数赋值给目标对象的事件处理程序属性。
var btn = document.getElementById('myBtn')
btn.onclick = function(){
alert("Hi im a btn");
}
复制代码
其作用域为当前目标对象的作用域
2.3 DOM2级事件处理程序
DOM2 级事件处理程序主要定义了两个事件处理的方法
addEventListener() removeEventListener()
分别用来为目标对象添加和删除事件处理程序。
var btn = document.getElementById('myBtn');
btn.addEventListener('click',function(){alert(this.id)});
复制代码
DOM2级事件处理程序与DOM0级事件处理程序一样也都是在目标元素作用域内运行所以上例中会弹出myBtn。
DOM2级事件处理程序可以为同一个目标元素添加两个相同的事件处理程序如:
var btn = document.getElementById('myBtn');
btn.addEventListener('click',function(){alert('one')});
btn.addEventListener('click',function(){alert('two')});
复制代码
上例中为btn添加了两个事件处理程序,其在页面中的执行顺序也是自上而下的。即先弹出one后弹出two。
通过addEventListener添加的事件处理程序只能用removeEvenListener来移除,但是如果addEventListener中的事件处理程序是一个匿名函数则及时在removeEventListener中也使用同样的匿名函数也是无法移除的因为此时这两个匿名函数指向的不是同一个函数对象,因此如果想要移除addEvenListenr中的事件处理函数则此处的事件处理函数必须为非匿名函数。
2.4 IE事件处理程序
IE中实现了和DOM中类似的两个方法attachEvent()
和 detachEvent()
这两个方法也分别接收事件处理程序名称和处理函数。
IE中的事件处理程序与DOM2级事件处理程序主要有三个方面的区别
- 事件处理函数中的作用域是全局作用域而不是目标对象;
- 同个目标对象上绑定的相同的动作,其事件处理程序执行顺序是从后往前的
- 这两个方法的第一个参数是'on'加上相关的动作名,与DOM0级事件处理程序类似。
2.5 跨浏览器的事件处理程序
var EventUtil = {
addHandler:function(elem,action,func){
if(elem.addEventListener){
elem.addEventListener(action,func,false);
}else if(elem.attachEvent){
elem.attachEvent("on"+action,func);
}else{
elem["on"+action] = func;
}
},
removeHandler:function(elem,action,func){
if(elem.removeEventListener){
elem.removeEventListener(action,func);
}else if (elem.detachEvent) {
elem.detachEvent("on"+action,func);
}else {
elem["on"+action] = null;
}
}
}
复制代码