闲来无事想总结一下js中有关事件的知识点。
###一、事件流
为啥要叫事件流呢,这是因为当在一个html页面中某个元素触发一个事件的时候,接收这个事件的元素不止一个,而是多个,所以我们使用事件流描述页面中接收事件的顺序。目前存在的事件流主要有两种:
- 冒泡流
事件最开始由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐级向上传播至最不具体的那个节点(文档)。知持事件冒泡流结构的浏览器则涵盖了当下基本所有的浏览器,包括IE8及以前版本。 - 捕获流
它从不太具体的节点应该最早接收到事件,最具体的节点最晚接收到事件。这种事件流模型是由natScape浏览器独自开发的一种事件流结构,后来也被火狐、chrome、IE9及以上等主流浏览器支持。
目前用的比较多的是冒泡流我们举个例子来说明事件冒泡流。
<div id="d1">
<button id="btn1">btn1</button>
<button id="btn2">btn2</button>
</div>
<script>
var btn1=document.getElementById("btn1");
var d1=document.getElementById("d1");
btn1.onclick=function(){
alert("btn1");
};
d1.onclick=function(){
alert("d1");
}
</script>
上面这段代码当你点击 ‘btn1’ 这个按钮的时候,会先输出btn1,点击确定之后会在输d1。虽然我们仅仅是点击了btn1,但是触发事件的时候不是触发完btn1就停止了,而是继续向上冒泡触发btn1的父元素d1,这就是事件冒泡。
###二、事件处理程序
所谓事件处理程序就是当触发某个事件的时候,相应执行的动作。目前存在三种事件处理程序:HTML事件处理程序、Dom0级事件处理程序和Dom2级处理程序。
- HTML事件处理程序
//body中的元素中直接添加onclick方法
<input type="button" id="btn1" onclick="show()">
<form method="post">
<imput type="text" name="username" value="">
<imput type="button" name="" value="" onclick="show(username.value)">
</form>
//然后在js中写事件处理程序
function showMessage(){
alert("hello world");
}
这样指定事件处理程序会创建封装着元素属性值的函数,另一个有意思的地方是它扩展了作用域,在事件处理函数内部,可以像访问局部变量一样访问document以及元素本身成员。
这种方式缺点很明显:
- 缺点–JS代码和html代码紧密耦合,当需要修改时,JS 代码和 HTML 代码均需要修改。
- 扩展作用域在不同浏览器中可能在解析会出问题。
- Dom0级事件处理程序
//要给btn2按钮添加点击事件处理程序
<input type="button" id="btn2">
//在js代码区添加事件处理程序和绑定关系
var btn2 = document.getElementById("btn2");
btn2.onclick = function showMessage(){
alert("hello world");
}
这种方法把js和html分开,具有松耦合;并且它的支持度最为广泛,涵盖了IE系列浏览器。 是一种比较好的方式。
但是无论是1还是2都有一个很大的缺点就是它们只能给一个一个事件添加一个事件处理程序,如果给一个事件添加多个事件处理程序的话,后面的事件处理程序会覆盖前面的。
3. Dom2级处理程序
//假设要给btn2按钮添加点击事件处理程序
<input type="button" id="btn3">
//js区添加事件处理程序和绑定关系
function showMessage(){
alert("hello world");
}
var btn3 = document.getElementById("btn3");
//Chrome,firefox等浏览器中的写法,IE9及以上版本也支持
btn3.addEventListener("click", showMessage, false);
btn3.removeEventListener("click", showMessage,
false);
//在IE8及以下中的写法, IE9、IE10也支持,IE11不再支持
btn3.attachEvent("onclick", showMessage);
btn3.detachEvent("onclick", showMessage);
这里Chrome中的第一个参数和IE浏览器第一参数的区别 ,前者为“click”, 后者为“onclick”。Chrome中的第三个参数,true标示事件捕获流,false标示事件冒泡流。Dom2的方式可以给一个事件添加多个事件处理程序,后边的事件处理程序并不会覆盖前面的,而是会依次执行。
所以由于Dom2在IE和Chrome中添加和使用的方法不同,所以我们为了兼容,通常会封装一个对象:
ar 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;
}
}
}
###三、事件对象
当我们触发一个事件的时候,会同时产生一个事件对象,这个对象记录着和这个事件有关的一切信息。比如:
//下面这段代码中的event就是触发点击事件产生的事件对象。
<button id="btn1">btn1</button>
var btn1=document.getElementById("btn1");
btn1.addEventListener("click",function(event){
console.log(event.target);
在这里我们介绍一下事件对象event中最重要的几个事件和方法:
-
非IE浏览器(event)
-
事件对象属性
type:描述事件类型。
target:描述事件所在元素。 -
事件对象方法
stopPropagation():阻止事件的冒泡
preventDefault():取消元素默认的行为 -
IE浏览器
-
事件对象属性
type:描述事件类型。
srcElement:描述事件所在元素。
cancelBubble:阻止事件的冒泡
returnValue:取消元素默认的行为
描述事件类型指的是给出事件的名称。描述事件所在的元素指的是给出这个事件绑定的元素。阻止事件冒泡是指的只触发这个事件并不会向上冒泡。取消元素默认的行为是取消元素本来默认的行为,比如可以通过这个函数取消a标签的点击它默认会跳转的行为。值得注意的是IE浏览器中都是属性,并没有方法。