javascript事件机制

转[url]http://www.jb51.net/article/22107.htm[/url]

Javascript中的事件都是与对象相关联的,而不是语言本身所有,当Javascript在浏览器中运行的时候,事件与每个浏览器实现的DOM模型有关。
事件本身相当直观,常用的有:

[img]http://dl.iteye.com/upload/attachment/370982/5f9c785a-6f19-3602-8229-5601eb994114.png[/img]
1. 0级DOM上的事件处理
0级DOM上的事件处理方法是比较早的,目前也广泛应用,从IE4.0开始就支持这类方法。

[b]1.1 事件注册 [/b]
下面主要介绍如何添加响应事件,也就是为事件添加处理程序。

[b](1)内联注册(inline registration)[/b]

这是最简单的一种,将事件响应程序作为html标签的一个属性来设置,如下例,可以是代码,当然更多情况下是一个函数调用。事件的句柄一般就是事件的名称加上前缀on。

<html>
<head>
<title>event sample</title>
<style type="text/css">
#adiv {
width: 200px;
height: 200px;
background-color: #00aa00;
}
</style>

</head>
<body>
<div id="adiv" onmouseover="this.innerHTML+='OK'">
a
</div>
</body>
</html>
这种方法很简单,任何浏览器都支持,缺点是将Javascript代码和HTML代码混杂在一起,而且不能动态添加事件响应程序,也不能添加多个响应程序。
[b](2)传统模式(traditional registration)[/b]

这种模式将事件作为对象的属性进行添加。例如:

<script type="text/javascript">
function helloWorld() {
alert("Hello World");
var d = document.getElementById("adiv");
d.onmouseout = function() {
this.innerHTML += 'Bye';
}
}
window.onload = helloWorld;
</script>

[b]1.2 事件的参数(Event对象) [/b]
有些事件处理程序需要一些关于事件更多的信息,比如click事件发生的位置等。这些信息是通过事件参数传给事件处理程序的。IE事件模型和W3C事件模型对此的实现是不同的。

IE把event对象作为window对象的一个属性,而W3C把event对象作为处理程序的一个参数。下面以click事件为例,分别写一个程序用于IE和支持W3C标准的浏览器。

<html>
<head>
<title>event sample</title>
<style type="text/css">
#adiv {
width: 200px;
height: 200px;
background-color: #00aa00;
}
</style>
<script type="text/javascript">
function IEClick() {
var res = document.getElementById("result");
var s;
for (var p in window.event) {
s += p.toString() + ":" + window.event[p] + "\r\n";
}
res.innerHTML = s;
}
function W3CClick(args) {
var res = document.getElementById("result");
var s;
for (var p in args) {
s += p.toString() + ":" + args[p] + "\r\n";
}
res.innerHTML = s;
}
</script>
</head>
<body>
<div id="adiv" onclick="W3CClick(event)">a</div>
<div id="result" style="font-size:small; font-family:Verdana">
</div>
</body>
</html>

这一段页面代码可以把click事件对象的所有属性都展示出来。上面的例子是W3C的浏览器所用的方法,要在IE下使用,只要改成οnclick=”IEClick()”.注意,W3CClick中的参数名,只能是event。打印出来的属性很多,我分别用FF3.5,Chrome3,IE8(标准模式和兼容模式)运行,他们共有的属性并不多,其实也就这些共有的属性才有意义,他们是:

altKey,shiftKey,ctrlKey:是否按下alt,shift,ctrl键

clientX,clientY:客户区坐标(浏览器窗口),screenX,screenY:屏幕区坐标

[b]type:事件类型[/b]

虽然事件的参数的传递方式有点不同,但是对于写跨浏览器的代码也没有造成太多的麻烦,只需要在函数一开始判断下window.event有没有定义即可。


function BothClick(args) {
var evnt = window.event ? window.event : args;
alert(evnt.clientX);
}

注册句柄为:<div id="adiv" οnclick="BothClick(event)" >a</div>如果采用第二种方式注册句柄,则不需要什么特别处理。
[b]1.3 事件的浮升 [/b]
页面上的对象通常是重叠的,比如一个div中可以包括若干div或者其他元素。当某一事件触发的时候,同时有多个元素受影响,并且它们都有相应的事件处理程序,那么这些事件处理程序执行哪些?以何种顺序执行?这就是本节要讨论的问题。通常情况下,一个事件被多个句柄捕获的情形并不多见。先看一个例子(CSS省略):

<html>
<head>
<script type="text/javascript">
function body_click() {
var dis = document.getElementById("res");
dis.innerHTML += "Body Click ";
}
function out_click() {
var dis = document.getElementById("res");
dis.innerHTML += "Outer Click";
}
function inner_click() {
var dis = document.getElementById("res");
dis.innerHTML += "Inner Click ";
}
</script>
</head>
<body onclick="body_click()">
<div id="out" onclick="out_click()">
Outer Div
<div id="innerdiv" onclick="inner_click()">
Inner Div
</div>
</div>
<div id="res">
</div>
</body>
</html>

可见,事件是由内向外层的元素依次触发的。(一般教材上的说法是向上浮升,bubbling,我觉得这个向上是有歧义的,我一开始就误认为内层的元素是上面的,因为它能覆盖外层的元素)用0级DOM注册的事件,它的浮升方法无论是IE还是W3C都是统一的。
[b]1.4 浮升的取消 [/b]
有时候我们需要在响应了一个事件之后,就不需要外层的元素再响应了,可以取消事件的浮升。取消的方法IE和W3C是不一致的。IE是通过设置事件对象的cancelBubble属性来实现,W3C则是调用事件对象的stopPropagation方法。

例如上面的例子改为:

<html>
<head>
<script type="text/javascript">
function body_click() {
var dis = document.getElementById("res");
dis.innerHTML += "Body Click ";
}
function out_click() {
var dis = document.getElementById("res");
dis.innerHTML += "Outer Click";
}
function inner_click(arg) {
var evnt = window.event ? window.event : arg;
var dis = document.getElementById("res");
dis.innerHTML += "Inner Click <br/>";
if (evnt.stopPropagation) {
evnt.stopPropagation();
} else {
evnt.cancelBubble = true;
}
}
</script>
</head>
<body onclick="body_click()">
<div id="out" onclick="out_click()">
Outer Div
<div id="innerdiv" onclick="inner_click(event)">
Inner Div
</div>
</div>
<div id="res">
</div>
</body>
</html>

[b]1.5 事件处理函数中的this [/b]
这个this指向的是触发事件的对象。

下面介绍2级DOM的事件句柄。这种方式是比较新的方式,它不依赖于任何特定的事件句柄属性。W3C规定的方式是

object.addEventListener('event',function,boolean)

第一个参数是事件名,第二个是事件响应函数,第三个变量如果是true,则事件函数在事件冒泡阶段被触发,否则是在事件的捕获阶段被触发。W3C规定事件的发生有两个阶段,首先是捕获,即事件以此从最外层层的元素向内层传递,相应的事件处理函数被依次触发,然后是冒泡阶段,事件从最内层的元素向外层传递。 看一个例子:

<html>
<head>
<title>DOM 2 Event</title>
<script type="text/javascript">
function setup() {
var div = document.getElementById('testDiv');
div.addEventListener('click', function() {
alert('div true');
}, true);
document.addEventListener('click', function() {
alert('body true');
}, true);
div.addEventListener('click', function() {
alert('div false');
}, false);
document.addEventListener('click', function() {
alert('body false');
}, false);
}
window.onload = setup;
</script>
</head>
<body>
<div id='testDiv' style="width:100px;height:100px;background-color:gray"></div>
<body>
</html>

点击灰色框,会依次弹出body true,div true,div false,body false. 很遗憾,IE不支持这种方式,最新的IE8也不支持。不过IE也有类似的注册事件的方法,名字是attachEvent.不过这个方法没有第三个参数,它支持冒泡阶段的事件响应。attachEvent函数传递事件参数的时候是和W3C一致的,也是通过event参数传递,但是,其函数内部的this指向的不是触发事件对象,而永远指向window。在event对象中有一个属性指向触发该事件的对象,W3C中是target,IE中是srcElement, 在符合W3C规范的浏览器中,事件处理函数中的this和event.target指向的是同一个对象。下面的程序展示了一个IE和W3C兼容的事件处理程序:

<html>
<head>
<title>DOM 2 Event</title>
<script type="text/javascript">
function ClickMe(event) {
var target1 = event.target ? event.target : event.srcElement;
alert(target1.innerHTML);
}
function setup() {
var div = document.getElementById('testDiv');
if (div.addEventListener) {
div.addEventListener('click', ClickMe, false);
} else {
div.attachEvent('onclick', ClickMe);
}
}
window.onload = setup;
</script>
</head>
<body>
<div id='testDiv' style="width:100px;height:100px;background-color:gray">
Hello World.
</div>
</body>
</html>


事件处理程序中W3C和IE还有诸多不一致之处,十分麻烦。好在大多都有较好的解决方案。更多信息请参考http://www.quirksmode.org/js/events_events.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值