javascript 事件处理
2015-07-10 22:55
621 查看
【写在前面】最近一直在看js的基础,毕竟jquery虽然好用,总归是用着别人写的,只会用api不如搞清楚实现的原理。等把js基础巩固好了一定要去读jquery的源码。
当单击div时,事件首先在div上响应,然后传到body元素上,然后传到html元素上,最后传到document对象。
捕获流正好相反,最先响应的是document对象,然后沿dom树依次向下,到html,到body,最后到实际目标,也就是div。
老版浏览器并不支持捕获流,冒泡流也非常符合我们对事件传播的理解,因此我们更多使用的是冒泡流。
也可以调用其他地方定义的脚本:
使用直接绑定有两个特别的地方,其一是会创建一个封装元素属性的函数,这个函数中有一个局部变量event,也就是事件对象:
事件产生时,event对象自动传递到showMessage函数中,通过这个对象我们可以访问到事件对象的很多属性。另外在事件处理程序内部,this指代事件的目标元素,比如
另外当当前元素是一个表单元素时,则作用域中还会包含表单元素的入口,也就是说在事件处理程序中可以访问其他表单元素,例如
这样可以直接输出username中的值。
然而通过这种方式添加的事件处理虽然直观方便,但有很多坏处:
(1)因为页面加载顺序是从上往下,如果绑定的脚本写在html下面,可能用户点击元素的时候脚本还未执行,造成用户点半天没反应,如:
(2)html和js代码紧密结合,比如showMessage这个方法,如果界面内很多元素都通过这种方式绑定了这个方法,那么如果某一刻想给这个函数换一个名字时,你需要同时改动很多处地方,相当麻烦。
通过DOM0级方法指定的程序被认为是元素的方法,所以上述代码执行后,按下元素弹出的将是按钮的id,可以通过this获取该元素所有的属性和方法。
需要删除通过DOM0级方法指定的事件处理程序,只需将该属性值设为null即可:
需要注意的是通过这种方式不能为元素添加重复事件,多次为onclick赋值只有最后一个是有效的,比如
最后单击按钮的时候只会输出second。
“DOM2级事件”定义了两个方法,用于指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点都有这个方法,并接收3个参数:事件名、事件处理函数和一个布尔值。这个布尔值代表了是使用捕获还是冒泡,true代表在捕获阶段处理,false代表在冒泡阶段处理,不填默认是false。
和DOM0级事件处理不同,通过这种方法绑定的事件处理可以多次添加,比如
而且在函数内this同样指代目标元素,点击按钮后会先输出first,再输出该btn的id。
通过addEventListener添加的事件只能通过removeEventListener移除,而且参数必须一样(三个参数一模一样),这代表使用匿名函数绑定的事件是无法移除的,最好将事件处理函数单独定义。
IE事件处理同之前的其他方式有两个区别,第一,IE的事件处理程序会在全局环境下运行。
这代表在其中使用this会等于window。
第二,多次添加的事件处理函数按添加的相反顺序执行,比如
当按下按钮时,将先输出second,然后才输出first。
要移除事件的方式同DOM2级相似,调用detachEvent然后传如相同参数即可。
实现方式是先判断是否支持DOM2级处理,如果不支持采用IE方法,如果都不支持最后采用DOM0级方法。
事件流
事件流描述的是从页面中接收事件的顺序。js中有两种事件流,冒泡流和捕获流。两种流的名称都很形象,在由节点构成的一颗html树上面,冒泡流指事件开始时候由最具体的元素最先接收,然后逐级传播到最不具体的节点,比如在如下文档中:<!doctype html> <html> <head></head> <body> <div></div> </body> </html>
当单击div时,事件首先在div上响应,然后传到body元素上,然后传到html元素上,最后传到document对象。
捕获流正好相反,最先响应的是document对象,然后沿dom树依次向下,到html,到body,最后到实际目标,也就是div。
老版浏览器并不支持捕获流,冒泡流也非常符合我们对事件传播的理解,因此我们更多使用的是冒泡流。
事件处理的几种方法
在js的事件处理中定义了很多种事件,事件名称是指具体的某种动作,比如click、load、mouseover等都是事件的名称。而响应某个事件的函数叫事件处理程序,事件处理程序的名字是以on开头的,因此click事件的事件处理程序就是onclick,load事件的事件处理程序就是onload。标签内绑定
通过设置标签的属性可以为节点十分方便地绑定事件,如:<input type="button" value="按钮" onclick="alert('按钮按下')">
也可以调用其他地方定义的脚本:
<script> function showMessage(){ alert("按钮按下"); } </script> ... <input type="button" value="按钮" onclick="showMessage()">
使用直接绑定有两个特别的地方,其一是会创建一个封装元素属性的函数,这个函数中有一个局部变量event,也就是事件对象:
<!--输出'click'--> <input type="button" value="按钮" onclick="showMessage(event.type)">
事件产生时,event对象自动传递到showMessage函数中,通过这个对象我们可以访问到事件对象的很多属性。另外在事件处理程序内部,this指代事件的目标元素,比如
<!--输出'按钮'--> <input type="button" value="按钮" onclick="showMessage(this.value)">
另外当当前元素是一个表单元素时,则作用域中还会包含表单元素的入口,也就是说在事件处理程序中可以访问其他表单元素,例如
<form> <input type="text" name="username"/> <input type="button" value="按钮" onclick="alert(username.value)"> </form>
这样可以直接输出username中的值。
然而通过这种方式添加的事件处理虽然直观方便,但有很多坏处:
(1)因为页面加载顺序是从上往下,如果绑定的脚本写在html下面,可能用户点击元素的时候脚本还未执行,造成用户点半天没反应,如:
<input type="button" value="按钮" onclick="showMessage()"> ... ...//很多内容 ... <script> function showMessage(){ //... } </script>
(2)html和js代码紧密结合,比如showMessage这个方法,如果界面内很多元素都通过这种方式绑定了这个方法,那么如果某一刻想给这个函数换一个名字时,你需要同时改动很多处地方,相当麻烦。
DOM0级处理程序
第二种方式是在js中为元素绑定事件,通过在js中获取元素,然后给其指定事件:var btn = document.getElementById("button"); btn.onclick = function(){ alert(this.id); }
通过DOM0级方法指定的程序被认为是元素的方法,所以上述代码执行后,按下元素弹出的将是按钮的id,可以通过this获取该元素所有的属性和方法。
需要删除通过DOM0级方法指定的事件处理程序,只需将该属性值设为null即可:
btn.onclick = null;
需要注意的是通过这种方式不能为元素添加重复事件,多次为onclick赋值只有最后一个是有效的,比如
btn.onclick = function(){ alert("first"); } btn.onclick = function(){ alert("second"); }
最后单击按钮的时候只会输出second。
DOM2级处理程序
IE9、Firefox、chrome、safari和opera支持DOM2级事件处理程序“DOM2级事件”定义了两个方法,用于指定和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点都有这个方法,并接收3个参数:事件名、事件处理函数和一个布尔值。这个布尔值代表了是使用捕获还是冒泡,true代表在捕获阶段处理,false代表在冒泡阶段处理,不填默认是false。
var btn = document.getElementById("button"); btn.addEventListener("click", function(){ //... }, false);
和DOM0级事件处理不同,通过这种方法绑定的事件处理可以多次添加,比如
var btn = document.getElementById("button"); btn.addEventListener("click", function(){ alert("first"); }, false); btn.addEventListener("click", function(){ alert(this.id); }, false);
而且在函数内this同样指代目标元素,点击按钮后会先输出first,再输出该btn的id。
通过addEventListener添加的事件只能通过removeEventListener移除,而且参数必须一样(三个参数一模一样),这代表使用匿名函数绑定的事件是无法移除的,最好将事件处理函数单独定义。
btn.addEventListener("click", function(){ alert("first"); }, false); btn.removeEventListener("click", function(){ alert("first"); }, false); //没有效果 btn.addEventListener("click", showMessage, false); btn.removeEventListener("click", showMessage, false); //移除成功
IE事件处理程序
IE中单独实现了与DOM2级事件处理中类似的两个方法:attachEvent和detachEvent()。这两个方法接收两个参数:事件处理程序名称和事件处理函数。因为IE8及更早版本只支持事件冒泡,所以通过这种方式添加的事件处理程序都会被添加在事件冒泡阶段。var btn = document.getElementById("button"); btn.attachEvent("onclick", function(){ //注意是onclick alert("first"); });
IE事件处理同之前的其他方式有两个区别,第一,IE的事件处理程序会在全局环境下运行。
这代表在其中使用this会等于window。
var btn = document.getElementById("button"); btn.attachEvent("onclick", function(){ alert(this === window); //true });
第二,多次添加的事件处理函数按添加的相反顺序执行,比如
var btn = document.getElementById("button"); btn.attachEvent("onclick", function(){ alert("first"); }); btn.attachEvent("onclick", function(){ alert("second"); });
当按下按钮时,将先输出second,然后才输出first。
要移除事件的方式同DOM2级相似,调用detachEvent然后传如相同参数即可。
编写跨浏览器的事件处理程序
上面提到IE和其他浏览器在处理事件上还是存在一些差异的,可以编写一个EventUtil对象,来将添加事件和移除事件封装起来。实现方式是先判断是否支持DOM2级处理,如果不支持采用IE方法,如果都不支持最后采用DOM0级方法。
var EventUtil = { //添加事件 addHandler: function(element, type, handler){ if(element.addEventListener){ //支持DOM2级 element.addEventListener(type, element, handler); }else if(element.attachEvent){ //IE事件处理,注意on前缀 element.attachEvent("on" + type, handler); }else{ //DOM0级 element["on" + type] = handler; } }, //移除事件 removeHandler: function(){ if(element.removeEventListener){ //支持DOM2级 element.removeEventListener(type, element, handler); }else if(element.detachEvent){ //IE事件处理,注意on前缀 element.detachEvent("on" + type, handler); }else{ //DOM0级 element["on" + type] = null; } } }
相关文章推荐
- JQuery1——基础($对象,选择器,对象转换)
- Android学习笔记(二九):嵌入浏览器
- Android java 与 javascript互访(相互调用)的方法例子
- JavaScript演示排序算法
- javascript实现10进制转为N进制数
- 2019年开发人员应该学习的8个JavaScript框架
- HTML中的script标签研究
- 异步流程控制:7 行代码学会 co 模块
- JavaScript拆分字符串时产生空字符的原因
- IE8开发人员工具教程(二)
- Mootools 1.2教程 事件处理
- 在flex中执行一个javascript方法的简单方式
- Flex结合JavaScript读取本地路径的方法
- jQuery中的常用事件总结
- C#实现WinForm捕获最小化事件的方法
- PowerShell中执行Javascript的方法示例
- javascript asp教程第六课-- response方法
- javascript asp教程More About Recordsets
- javascript asp教程第十二课---session对象