轻松学习JavaScript二十七:DOM编程学习之事件模型
在介绍事件模型之前,我们先来看什么是事件和什么是event对象。
一事件介绍
JavaScript事件是由訪问Web页面的用户引起的一系列操作,使我们有能力创建动态页面。事件是能够被
JavaScript侦測到的行为。
网页中的每一个元素都能够产生某些能够触发JavaScript函数的事件。例如说。我们能够在用
户点击某button时产生一个onclick事件来触发某个函数。事件在HTML页面中定义;事件通常与函数配合使用,当事件
发生时函数才会运行;事件一般用于浏览器和用户操作进行交互。
我们经经常使用到的事件举例:鼠标点击,页面或图像加载,鼠标悬浮于页面的某个热点之上,在表单中选取输入
框,确认表单。键盘按键等等。
二event对象
Event对象代表事件的状态,比方事件在当中发生的元素、键盘按键的状态、鼠标的位置、鼠标button的状态。
事
件通常与函数结合使用,函数不会在事件发生前被运行!
当触发某个事件时,会产生一个事件对象。这个对象包括着全部与事件有关的信息。包括导致事件的元素。事件
的类型,以及其他与特定事件相关的信息。事件对象我们一般称作event对象。这个对象是浏览器通过函数把这个对
象作为參数传递过来的。那么我们能够验证一下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM</title> <script type="text/javascript"> //定义的普通函数 function box(){ alert(arguments.length);//输出:0 }; //函数调用 box(); window.onload=function(){ //得到input对象 var input=document.getElementsByTagName("input")[0]; //匿名函数运行 input.onclick=function(){ alert(arguments.length);//输出:1,得到一个隐藏的參 alert(arguments[0]);//输出:object MouseEvent表示鼠标事件对象 }; } </script> </head> <body> <input type="button" value="按钮" /> </body> </html>
通过上面两组函数,我们得到。通过事件绑定的运行函数是能够得到一个隐藏參数的,说明浏览器会自己主动分配一
个參数,这个參数就是为event对象。我们是能够直接接受event对象的,W3C和IE分别用不同的方法得到:W3C的是
直接传递event对象作为參数,而IE须要使用window.evevt才干获取得到。
我们来做一下兼容:
window.onload=function(){ //得到input对象 var input=document.getElementsByTagName("input")[0]; //匿名函数运行 input.onclick=function(event){ var event=event||window.event; alert(event);//输出:object MouseEvent表示鼠标事件对象 }; }
我们既然得到event对象,因此我们能够操作一些event对象的属性和方法:
标准Event属性
标准Event方法
因为DOM2级标准事件模型,IE9之前的低版本号浏览器并不支持。IE9已经全面支持了。我们就不再做浏览器兼容
的属性和方法。
在真正用到的时候我们再进行视情况而定的兼容。
三事件模型
(1)内联模型
内联模型是最传统接单的一种处理事件的方法。在内联模型中,事件处理函数是HTML标签的一个属性。用于处
理指定事件。尽管内联在早期使用较多,可是它是和html混写的,并没有与html分离,而且写入的代码数量非常少,并
不有用。
以下看一个内联模型的演示样例:
<!--在HTML中把事件处理函数作为属性运行JS代码--> <input type="button" value="按钮" onclick="alert('I am JS code!');" />
另一个内联模型的应用,这个也实现了JS代码和HTML一定的分离。但还是属于内联模型。JS函数写在JS文件
中:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM</title> <script type="text/javascript"> function box(){ alert("I am JS code!"); } </script> </head> <body> <!--在HTML中把事件处理函数作为属性运行JS函数--> <input type="button" value="按钮" onclick="box();" /> </body> </html>
(2)脚本模型
因为内联模型违反了HTML与JavaScript代码层次分离的原则,为了解决问题。我们尝试在JavaScript中进行
事件处理。这样就产生了脚本模型。示比例如以下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM</title> <script type="text/javascript"> window.onload=function(){ //得到input对象 var input=document.getElementsByTagName("input")[0]; //匿名函数运行 input.onclick=function(){ alert("I am JS code!"); }; } </script> </head> <body> <input type="button" value="按钮" /> </body> </html>
通过匿名函数能够运行onclick事件,即能够直接触发相应的代码。还有还有一种方式也能够实现,那就是通过指定
的函数名赋值的方式来运行函数,注意赋值的函数名不要带着括号。
和上面有差别的就是JS代码部分:
window.onload=function(){ //得到input对象 var input=document.getElementsByTagName("input")[0]; //通过赋值指定的函数名运行 input.onclick=box; function box(){ alert("I am JS code!"); }; }
(3)DOM2级模型
在介绍DOM2模型之前我们的先了解什么是事件流。
事件流是描写叙述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候,那么你点击当中一个元
素。并非仅仅有当前被点击的元素会触发事件,而层叠在你点击范围内的全部元素都会出发事件。事件流包含两种模
式:冒泡和捕获。
以下的图示非常好的展示了事件流:
事件冒泡,是从里往外逐个触发。事件捕获。是从外往里逐个触发。
现代浏览器默认情况下都是冒泡模型。我们
能够使用DOM2级模型的事件绑定机制手动定义事件流模式。
在全部的现代浏览器其中——除了IE9之前的版本号,都实现了DOM2标准事件模型。这个事件模型规定:每个
DOM元素所触发的事件都要经历三个阶段:捕获阶段;目标对象本身的事件处理程序调用阶段;冒泡阶段。
冒泡阶段:当文档元素上发生某个类型的事件时。他们会在文档树上向上传播,即调用父元素的同样类型的事件
处理函数。
捕获阶段:捕获阶段像是反向的冒泡阶段。
最先调用window对象的捕获处理程序,然后是document对象的捕获处
理程序,接着是body对象的,再然后是Dom树向下。以此类推。直到调用事件目标元素的父元素的捕获事件处理程
序。在目标元素对象本身上注冊捕获事件处理程序不会被调用。
在DOM2级标准事件模型中。为一个DOM元素绑定事件的方法是addEventListener()方法,这种方法要求传递三
个參数,第一个參数为一个字符串。表示事件的类型。如"click";第二个參数是一个函数。表示事件处理程序,浏览
器会默觉得该函数传递一个事件对象也就是event对象;第三个參数是一个布尔值,布尔值为false表示此函数将注冊
为冒泡事件处理程序(通常设置为false就可以),假设值为true,表示此函数将注冊为捕获事件处理程序。值得注意的
是,能通过多次调用addEventListener()方法为同一个对象注冊同一事件类型的多个处理程序函数。当对象上发生事
件时,全部该事件类型的注冊处理程序都会依照注冊的顺序调用。
分析事件的触发过程,分两种情况:
1当目标元素不存在父元素或目标元素的父元素并没有注冊与触发目标元素同样类型的事件时,事件模型的第一
和第三阶段是没有实际意义的,即不会发生不论什么的事情。
2当目标元素存在父元素且目标元素的父元素注冊了与触发目标元素同样类型的事件时。事件模型的第一和第三
阶段就開始起作用了。
我们在这里看一个非常easy的样例:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> <title>DOM</title> <script type="text/javascript"> window.addEventListener("load",function(){ alert("I am JS code!"); },false) </script> </head> <body> <input type="button" value="按钮" /> </body> </html>
上面的addEventListener()方法IE9之前的低版本号浏览器并不兼容,而且进行绑定的时候会有诸多的问题出现。IE
不支持捕获,仅仅支持冒泡;IE加入事件不能屏蔽反复的函数。IE中的this指向的是window对象而不是DOM对象。可能
对于低版本号的IE浏览器不兼容。可是IE9全然支持W3C中的事件绑定函数。
对于怎么做到兼容。还是在详细的实际项
目中灵活应用。