前端JS的事件处理

计算机应用技术web前端开发 云南前端开发招聘 最新前端开发的技术
一、DOM事件流
DOM(文档对象模型)结构是一个树型结构,当一个html元素产生一个事件时,该事件会在元素节点和根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程称为DOM事件流。
事件顺序有两种模型:事件捕获和事件冒泡。
(1)冒泡型事件(Event Bubbling)
这是IE浏览器对事件模型的实现,也是最容易理解的。冒泡,顾名思义,事件像个水中的气泡一样一直往上冒,直到顶端。从DOM树型结构上理解,就是事件由叶子节点沿祖先节点一直向上传递,直到根节点;从浏览器界面视图html元素排列层次上理解,就是事件由具有从属关系的最确定的目标元素一直传递到最不确定的目标元素。
冒泡型事件的基本思想,事件按照从特定的事件目标开始到最不确定的事件目标。
(2)捕获型事件(Event Capturing)
Netscape的实现,它与冒泡型刚好相反,由DOM树最顶层元素一直到最精确的元素。
DOM标准的事件模型:DOM标准同时支持两种事件模型,即捕获型事件与冒泡型事件,但是,捕获型事件先发生。两种事件流都会触发DOM中的所有对象,从document对象开始,也在document对象结束(大部分兼容标准的浏览器会继续将事件捕获/冒泡延续到window对象)。
[color=Red]DOM标准的事件模型最独特的性质是:文本节点也会触发事件(在IE不会)。
标准的事件传送模式:
(1)事件捕获阶段,事件将沿着DOM树向下传送,目标节点的每一个祖先节点,直至目标节点。例如,若用户单击了一个超链接,则该单击事件将从document节点传送到html元素,body元素以及包含该链接的p元素。在此过程中,浏览器都会检测针对该事件的捕获事件监听器,并且运行这个事件监听器。
(2)目标阶段,浏览器在查找到已经指定给目标节点的事件监听器之后,就会运行该事件监听器。目标节点就是触发事件的DOM节点。例如,如果用户单击一个超链接,那么该链接就是目标节点(此时的目标节点实际上是超链接内的文本节点)。
(3)冒泡阶段,事件将沿着DOM树向上传送,再次逐个访问目标元素的祖先节点到document节点。该过程的每一步,浏览器都将检测那些不是捕获事件监听器的事件监听器,并执行它们。
[color=Red]并非所有的事件都会经过冒泡阶段:
[color=DarkOrange]所有的事件都要经过捕获阶段和目标阶段,但是有些事件会跳过冒泡阶段。例如,让元素获得输入焦点的focus事件以及失去输入焦点的blur事件就都不会冒泡。
二、事件句柄与事件监听器
事件句柄和事件监听器的最大不同:使用事件句柄时一次只能插接一个事件句柄,但对于事件监听器,一次可以插接多个。
IE下的事件监听器:
IE提供的是一种自有的,完全不同的甚至存在bug的事件监听器,因此如果要让脚本在本浏览器中正常运行的话,就必须使用IE所支持的事件监听器。
在IE中,每个元素和window对象都有两个方法:attachEvent方法和detachEvent方法。
element.attachEvent(“onevent”,fn);
注意:[color=Red]IE下利用attachEvent注册的处理函数调用时,this指向不再是先前注册事件的元素,这时的this为window对象。
DOM标准下的事件监听器:
在支持W3C标准事件监听器的浏览器中,对每个支持事件的对象都可以使用addEventListener方法。该方法既支持注册冒泡型事件处理,又支持捕获型事件处理。所以与IE浏览器中注册元素事件监听器方式有所不同。
//标准语法
element.addEventListener(‘event’,fn,useCapture);
//默认
element.addEventListener(‘event’,fn,false);
第三个参数[color=DarkOrange]注明该处理回调函数是在事件传递过程中的捕获阶段被调用还是冒泡阶段被调用,通常此参数会设置为false(为false时是冒泡),那么,如果将其值设置为true,那就创建一个捕获事件监听器。
移除已注册的事件监听器调用element的removeEventListener方法即可,参数相同。
跨浏览器的注册与移除元素事件监听器方案
<script>
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;
}
}
};
</script>
事件对象引用
为了更好地处理事件,你可以根据所发生的事件的特定属性来采取不同的操作。
如事件模型一样,IE和其他浏览器处理方法不同:IE使用一个叫做event的全局事件对象来处理对象(它可以在全局变量window.event中找到),而其他所有浏览器采用W3C推荐的方式,使用独立的包含事件对象的参数传递。
<script>
var EventUtil = {
getEvent:function(event){
return event ? event : window.event;
},
getTarget:function(event){
return event.target || event.srcElement;
}
};
</script>
三、停止事件冒泡和阻止事件的默认行为
“停止事件冒泡”和“阻止浏览器的默认行为”,这两个概念非常重要,它们对复杂的应用程序处理非常有用。
1、停止事件冒泡
停止事件冒泡是指,停止冒泡型事件的进一步传递(取消事件传递,不只是停止IE和DOM标准共有的冒泡型事件,我们还可以停止支持DOM标准浏览器的捕获型事件,用stopPropagation()方法)。例如,在body处理停止事件传递后,位于上层的document的事件监听器就不再收到通知,不再被处理。
2、阻止事件的默认行为
阻止事件的默认行为是指,通常浏览器在事件传递并处理完成后会执行与该事件关联的默认动作(如果存在这样的动作)。例如,如果表单中input type属性是”submit”,点击后在事件传递完浏览器就自动提交表单。又例如,input元素的keydown事件发生并处理后,浏览器默认会将用户键入的字符自动追加到input元素的值中。
停止事件冒泡的处理方法:
在IE下,通过设置event对象的cancelBubble为true即可。
function someHandle(){
window.event.cancelBubble = true;
}
DOM标准通过调用event对象的stopPropagation()方法即可。
function someHandle(event){
event.stopPropagation();
}
因此,跨浏览器的停止事件传递的方法是:
function someHandle(event){
event = event || window.event;
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
阻止事件的默认行为的处理方法:
在IE下,通过设置event对象的returnValue为false即可。
function someHandle(){
window.event.returnValue = false;
}
DOM标准通过调用event对象的preventDefault()方法即可。
function someHandle(event){
event.preventDefault();
}
因此,跨浏览器的取消事件传递后的默认处理方法是:
function someHandle(event){
event = event || window.event;
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue = false;
}
}
完整的事件处理兼容性函数:
<script>
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;
}
}
};
</script>
四、捕获型事件模型与冒泡型事件模型的应用场合
1、捕获型应用场合
捕获型事件传递由最不精确的祖先元素一直到最精确的事件源元素,传递方式与操作系统中的全局快捷键与应用程序快捷键相似。当一个系统组合键发生时,如果注册了系统全局快捷键监听器,该事件就先被操作系统层捕获,全局监听器就先于应用程序快捷键监听器得到通知,也就是全局的先获得控制权,它有权阻止事件的进一步传递。[color=DarkOrange]所以捕获型事件模型适用于作全局范围内的监听,这里的全局是相对的全局,相对于某个顶层节点与该节点所有子孙节点形成的集合范围。
例如,你想作全局的点击事件监听,相对于document节点与document下所有的子节点,在某个条件下要求所有的子节点点击无效,这种情况下冒泡模型就解决不了了,而捕获型却非常适合,可以在最顶层节点添加捕获型事件监听器,伪代码如下:
function globalClickListener(event){
if(canEventPass == false){
//取消事件进一步向子节点传递和冒泡传递
event.stopPropagation();
//取消浏览器事件后的默认执行
event.preventDefault();
}
}
这样一来,当canEventPass条件为假时,document下所有的子节点click注册事件都不会被浏览器处理。
2、冒泡型的应用场合
可以说我们平时用的都是冒泡事件模型,因为IE只支持这模型。恰当利用该模型可以提高脚本性能。在元素一些频繁触发的事件中,如onmousemove,onmouseover,onmouseout,如果明确事件处理后没必要进一步传递,那么就可以大胆地取消它。此外,对于子节点事件监听器的处理会对父层监听器处理造成负面影响的,也应该在子节点监听器中禁止事件进一步向上传递以消除影响。
web开发前端技术总结 web前端开发技术ppt 做前端开发的技术
» 本文来自:前端开发者 » 《前端JS的事件处理》
» 本文链接地址:https://www.rokub.com/5531.html
» 您也可以订阅本站:https://www.rokub.com
赞(0)
64K

评论 抢沙发

评论前必须登录!