本篇文章主要讲解Javascript的事件,如下:
- 事件流
- 如何注册和删除事件
- 跨浏览器的事件处理程序和事件对象
- jquery触发事件的几种方式
事件是什么?
JavaScript与HTML之间的交互是通过事件实现的。
事件,就是文档或浏览器窗口中发生的一些特定交互瞬间,可以使用侦听器(或处理程序)来预订事件,以使事件发生时执行相应的代码。
事件流是什么?
事件流描述的是从页面中接收事件的顺序。
目前IE的事件流是事件冒泡流,Netscape的事件流是事件捕获流。
1、事件冒泡
事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点。
比如:
···
<body>
<div onclick="handleClick()">Click</div>
</body>
···
点击div时,click事件首先在div元素上发生,然后沿DOM树向上传播,在每一级节点上都会发生,直至传播到document对象。传播顺序为:
(1)<div>
(2) <body>
(3) <html>
(4) document
所有现代浏览器都支持事件冒泡,IE9、Firefox、Chrome和Safari将事件一直冒泡到window对象。(IE5.5及更早版本中的事件冒泡会跳过<html>元素,从<body>直接跳到document)
2、事件捕获
事件捕获,是不太具体的节点更早接收到事件,最具体的节点最后接收到事件。事件捕获的用意在于在事件到达预定目标之前捕获它。
以上面的click事件为例,document对象首先接收到cick事件,然后事件沿DOM树依次向下,一直传播到事件的实际目标,即<div>元素。
事件捕获的传播顺序为:
(1) document
(2) <html>
(3) <body>
(4) <div>
目前,IE9、Firefox、Chrome和Safari也支持事件捕获,不过都是从window对象开始捕获事件。
总结:IE8只支持事件冒泡,IE9、Firefox、Chrome和Safari既支持事件冒泡也支持事件捕获。
如何添加事件处理程序(注册事件)
1、HTML事件处理程序
元素支持的每种事件,都可以用一个与相应事件处理程序同名的HTML特性指定。这个特定的值应该是能够执行的JavaScript代码。
如下:
通过给按钮指定onclick特性绑定了click事件,当点击按钮时就会执行handleClick函数。其中this为事件的目标元素,this.value就是input的value值。
<body>
<input type="button" value="click me" onclick="handleClick(this)">Click</div>
</body>
<script>
function handleClick(){
console.log(this.value); //click me
}
</script>
这种注册事件的方式使HTML与JavaScript代码紧密耦合,如果要更换事件处理程序,既需要修改HTML又需要修改JavaScript,很麻烦。
兼容性:IE8+、chrome、firefox、opera、safari
2、DOM0级事件处理程序
就是通过JavaScript注册事件,将一个函数赋值给一个事件处理程序属性,每个元素都有自己的事件处理程序属性,比如onclick,如下:
首先取得要操作的元素对象的引用,然后给它指定事件处理程序,其中this为当前元素
<body>
<input id="btn" type="button" value="click me">Click</div>
</body>
<script>
var btn = document.getElementById('btn');
//绑定事件
btn.onclick = handleClick(){
console.log(this.value); //click me
}
</script>
//将事件处理程序属性值设置为null,即删除事件的绑定
btn.onclick = null;
//
兼容性:IE8+、chrome、firefox、opera、safari
3、DOM2级事件处理程序
就是使用addEventListener()注册事件,removeEventListener()删除事件addEventListener和removeEventListener都接受三个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值(如果是true,表示在捕获阶段调用事件处理程序;如果是false,表示在冒泡阶段调用事件处理程序)
注意:
- 用addEventListener注册事件,可以为一个元素同时添加多个事件处理程序,并且会按照他们的添加顺序触发
- 用addEventListener注册事件只能用removeEventListener移除,并且移除时传入的参数必须与注册时相同
<body>
<input id="btn" type="button" value="click me">Click</div>
</body>
<script>
var btn = document.getElementById('btn');
//下面代码移除事件时看似传入的参数一样,其实第二个参数是完全不同的两个函数
btn.addEventListener("click", function(){}, false); //添加事件处理程序
btn.removeEventListener("click", function(){}, false); //移除事件处理程序
//正确写法如下:
var handler1 = function() {
console.log(this.value);
};
var handler2 = function(){}
btn.addEventListener("click", handler1, false); //添加事件处理程序handler1
btn.addEventListener("click", handler2, false); //添加事件处理程序handler2
btn.removeEventListener("click", handler1, false); //移除事件处理程序handler1
btn.removeEventListener("click", handler2, false); //移除事件处理程序handle2
</script>
兼容性:IE9+、chrome、firefox、opera、safari
4、IE事件处理程序
就是attachEvent()和detachEvent()来注册事件和删除事件
attachEvent()和detachEvent()接受两个参数:事件处理程序名称和事件处理程序函数。
由于IE8只支持事件冒泡,所以通过attachEvent()注册事件会被添加到冒泡阶段。
注意:
- attachEvent()的第一个参数是"onclick",不是addEventListener中的click
- attachEvent()注册事件,是在全局作用域中运行,this等于window,而addEventListener注册事件是在其所属元素的作用域内运行。
- 用attachEvent注册事件只能用detachEvent移除,并且移除时传入的参数必须与注册时相同
- 用attachEvent注册事件,可以为一个元素同时添加多个事件处理程序,但不是按照添加顺序触发,而是相反顺序触发
<body>
<input id="btn" type="button" value="click me">Click</div>
</body>
<script>
var btn = document.getElementById('btn');
var handler1 = function() {
console.log(this.value);
};
var handler2 = function(){}
btn.attachEvent("onclick", handler1); //添加事件处理程序handler1
btn.attachEvent("onclick", handler2); //添加事件处理程序handler2
btn.detachEvent("onclick", handler1); //移除事件处理程序handler1
btn.detachEvent("onclick", handler2); //移除事件处理程序handle2
</script>
兼容性:IE和Opera
跨浏览器的事件处理程序和事件对象
以下是以跨浏览器的方式处理事件:
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;
}
},
//获取事件对象
getEvent: function(event) {
return event ? event : window.event;
},
//获取目标元素
getTarget: function(event) {
return event.target || event.srcElement;
},
//阻止事件默认行为
preventDefault: function(event) {
if(event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
//阻止冒泡
stopPropagation: function(event) {
if(event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
};
jQuery注册事件的几种方式
1、$(selector).click(function);
事件处理程序在元素作用域运行,this引用当前元素
$(selector). unbind("click"); //移除事件处理程序
2、$(selector).bind('click');
事件处理程序在元素作用域运行,this引用当前元素,
$(selector). unbind("click"); //移除事件处理程序
3、$(selector).delegate(childSelector, event, data, function);
delegate()方法为指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序。使用delegate()方法的事件处理程序适用于当前或者未来的元素(比如脚本创建的元素)。
如下是为iframe里id为ks-dialog-ok元素添加click事件,id为ks-dialog-ok元素是一个弹出框的确认按钮,iframe加载完时id为ks-dialog-ok元素还没有渲染,当触发某个操作弹出框才会渲染,所以需要用delegate为未来的元素绑定事件:
<iframe id="col-web" name="col-web" frameborder="0" width="720px" height="460px" onload="iframeOnload(this)"></iframe>
function iframeOnload(iframe) {
if(iframe.contentWindow.$) {
iframe.contentWindow.$(iframe.contentDocument).delegate("#ks-dialog-ok","click",function() {
$("#flash").hide();
})
}
}
4、$(selector).trigger(event, [param1,param2,...])
trigger() 方法触发被选元素的指定事件类型
triggerHandler()同trigger(),但是不可以冒泡
如下,当点击button时,就会触发input的文件上传,当觉得input文件上传按钮比较丑时,就可以自定义button按钮来覆盖原来按钮,利用trigger触发文件上传
<body>
<button id="btn">点击</button>
<input type="file">
</body>
<script>
$('#btn').click(function(){
$('input').trigger('click');
})
</script>