JavaScript DOM事件模型
早期由于浏览器厂商对于浏览器市场的争夺,各家浏览器厂商对同一功能的javascript的实现都不进相同,本节内容介绍javascript的dom事件模型及事件处理程序的分类。
1、dom事件模型。dom事件模型分为两种:事件冒泡和事件捕获。事件冒泡最初是微软提出的dom事件流的模型,顾名思义,就是值浏览器的事件流如同冒泡一样,从最低处到最高处。最低处对应的是dom中最具体的元素,最高处则是最外层元素,最外层元素一般就是document元素。
a、事件冒泡模型:
如下图,当点击最底层的span元素时,在冒泡模型中触发的事件流为:span的click事件触发---->父级元素div的click事件触发---->顶层的document元素的click事件触发。
b、事件捕获模型:
如下图,当点击span元素时,在事件捕获模型中触发的事件流为:最顶层的document的click事件首先被触发---->子容器div(同时也是span的父容器)的click事件被触发
---->最底层的span元素的click事件触发。
可见,事件冒泡和事件捕获的事件触发流程是完全相反的。
2、dom事件处理程序的分类。dom事件处理程序分为三种:html事件处理程序、dom 0级事件处理程序、dom 2级事件处理程序(注意:、没有dom1级事件处理程序)。
a、html事件处理程序:
指的是事件绑定直接写在html上,如:
1 <input type="button' value="button" onclick="alert('button clicked!')" />
这里button的click事件的绑定直接写在html中,这种写法即是html事件处理程序。由于这种写法造成html和javascript的紧耦合,当需要调整javascript事件时,不得不调整html代码(就算不修改javascript函数名,只修改函数的内部实现,仍然不推荐使用这种语法绑定事件,会增加不必要的维护成本)。
b、dom 0级事件处理程序:
指的是通过给javascript对象的事件参数属性赋值的模式,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.onclick = function(){ 5 alert("button clicked!"); 6 } 7 </script>
这里通过直接给btndom对象的onclick属性赋值的形式来绑定click事件就是dom 0级事件处理程序,赋值可以使用匿名函数的形式,也可以使用具名函数的形式,如下:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.onclick clickhandle; 5 function clickhandle(){ 6 alert("something clicked!"); 7 } 8 </script>
如需注销,只需将该属性设置为null即可,如下:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.onclick clickhandle; 5 function clickhandle(){ 6 alert("something clicked!"); 7 } 8 btn.onclick = null; 9 </script>
注意:如果绑定使用的是匿名函数的形式,通过给事件属性赋值null仍然可以注销该事件。
c、dom 2级事件处理程序:
指的是使用 addeventlistener("eventname","eventhandle",false),其中eventname表示事件名称、eventhandle表示事件处理函数,false表示是否启用事件捕获模式,默认为false。使用addeventlistener函数来给dom元素绑定事件处理程序,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.addeventlistener("click",function(){ 5 alert("something clicked!"); 6 },false); 7 </script>
同样,这里既可以使用匿名函数的形式也可以使用具名函数的形式,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.addeventlistener("click",clickhandle,false); 5 function clickhandle(){ 6 alert("something clicked!"); 7 } 8 </script>
注意:通过addeventlistener绑定的事件只能通过removeeventlistener来注销,不能使用dom 0级中的方式注销事件处理程序,注销事件如下:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.addeventlistener("click",clickhandle,false); 5 function clickhandle(){ 6 alert("something clicked!"); 7 } 8 btn.removeeventlistener("click",clickhandle); 9 </script>
如果绑定时使用的是匿名函数,则注销操作比较麻烦,可以通过事件参数的callee属性获取当前正在执行的函数,但必须使用在事件绑定的函数内,如:
1 <script> 2 var dom=document.getelementbyid("content"); 3 var clicknum=0; 4 dom.addeventlistener("click",function(e){ 5 clicknum++; 6 alert('你摸了我'+clicknum+'下了。最多摸2下哦'); 7 if(clicknum>=2){ 8 dom.removeeventlistener(e.type,arguments.callee,false); 9 console.log(this); 10 } 11 }); 12 </script>
d、ie中dom 2级事件处理程序的是通过attachevent来绑定的,语法与addeventlistener完全一致。
e、dom 0级和dom 2级事件处理程序的主要区别:
dom 2级事件处理程序可以给元素的事件绑定多个处理程序,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.addeventlistener("click",clickhandle1,false); 5 btn.addeventlistener("click",clickhandle2,false); 6 function clickhandle1(){ 7 alert("something clicked!"); 8 } 9 function clickhandle2(){ 10 alert("something clicked again!"); 11 } 12 </script>
此时,点击btn时将会依次触发clickhandle1、clickhandle2,注销事件处理程序也需要针对每个事件处理程序使用removeeventlistener。
dom 0级事件处理程序如果以这种形式绑定事件,则后写的方法会覆盖掉之前的方法,即:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getelementbyid("btn"); 4 btn.onclick = clickhandle1(); 5 btn.onclick = clickhandle2(); 6 function clickhandle1(){ 7 alert("something clicked!"); 8 } 9 function clickhandle2(){ 10 alert("something clicked again!"); 11 } 12 </script>
这里实际只会绑定clickhandle2方法,clickhandle1被后面的clickhandle2覆盖掉。
开发过程中推荐使用dom 0级事件处理程序或者dom 2级事件处理程序,如果只有一个事件处理程序dom 0级就足够了,当然,如需绑定多个事件处理程序,则需使用dom 2级事件处理程序。
为了屏蔽各浏览器之间的实现差异,推荐使用一些javascript库来辅助完成事件绑定。推荐使用jquery,针对不同的浏览器,可以使用统一的接口来完成这一过程。
上一篇: Python模拟微博登陆,亲测有效