js事件监听机制(事件捕获)总结

js事件监听机制(事件捕获)总结
在前端开发过程中我们经常会遇到给页⾯元素添加事件的问题,添加事件的js⽅法也很多,有直接加到页⾯结构上的,有使⽤⼀些js事件监听的⽅法,由于各个浏览器对事件冒泡事件监听的机制不同,le浏览器只有事件冒泡,没有事件监听的机制,对于事件监听的兼容性问题是最⼤的难题:
1.直接把事件的⽅法写在页⾯结构上
function eventfun(){
//console.log(this);
}
<input type="button" onclick="eventfun()" value="button" />//这⾥涉及到⼀个this作⽤域的问题,eventfun再这⾥是⼀个全局函数, 对象是[object Window],this指向的是window.
要解决this作⽤域的问题,可以使⽤为全局函数添加event变量的⽅法,在页⾯结构上将this对象作为参数传递到函数内部使⽤
<input type="button" onclick="eventfun2(this)" value="button2" />
function eventfun2(eve){//在这⾥把事件对象作为参数传递到全局⽅法⾥
eve.name="alex";
window.name="robin";
console.log(this);//[object Window]
console.log(eve);// [object HTMLInputElement]
console.log(this.name);// robin
console.log(eve.name);// alexvar
self=eve;
console.log(this.name);//robin
console.log(self.name);//alex
国民教育委员会alert(window.name);
alert(self.name);
}
2. 使⽤给事件属性赋值的⽅法,是⼀种为事件绑定的⽅法,但是这种⽅法的局限性就是只能为事件绑定⼀个⽅法,如果绑定多个就会以后⼀个⽅法为准lick = fucntion(){//使⽤这种为事件属性赋值的⽅法,this的指针会指向window对象,⽽不是被事件对象,所以这种⽅法是引⽤//js code
fun1();
fun2();
fun3();
console.log(this);//window.object
天然气利用政策}
function dosomething(){
/
/js code
}
console.log(this);//htmlElementObject
3.事件传播——冒泡与捕获
DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应⽤有着相当⼤的影响。这两种事件流分别是捕获和冒泡。和许多Web技术⼀样,在它们成为标准之前,Netscape和微软各⾃不同地实现了它们。Netscape选择实现了捕获事件流,微软则实现了冒泡事件流。幸运的是,W3C决定组合使⽤这两种⽅法,并且⼤多数新浏览器都遵循这两种事件流⽅式。
默认情况下,事件使⽤冒泡事件流,不使⽤捕获事件流。然⽽,在Firefox和Safari⾥,你可以显式的指定使⽤捕获事件流,⽅法是在注册事件时传⼊useCapture参数,将这个参数设为true。
冒泡事件流
当事件在某⼀DOM元素被触发时,例如⽤户在客户名字节点上点击⿏标,事件将跟随着该节点继承⾃的各个⽗节点冒泡穿过整个的DOM节点层次,直到它遇到依附有该事件类型处理器的节点,此时,该事件是onclick事件。在冒泡过程中的任何时候都可以终⽌事件的冒泡,在遵从W3C标准的浏览器⾥可以通过调⽤事件对象上的stopPropagation()⽅法,在Internet Explorer⾥可以通过设置事件对象的cancelBubble属性为true。如果不停⽌事件的传播,事件将⼀直通过DOM冒泡直⾄到达⽂档根。
捕获事件流
事件的处理将从DOM层次的根开始,⽽不是从触发事件的⽬标元素开始,事件被从⽬标元素的所有祖先元素依次往下传递。在这个过程中,事件会被从⽂档根到事件⽬标元素之间各个继承派⽣的元素所捕获,如果事件在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;否则,事件会被接着传递给派⽣元素路径上的下⼀元素,直⾄⽬标元素。事件到达⽬标元素后,它会接着通过DOM节点再进⾏冒泡。
现代事件绑定⽅法
针对如上节课所讨论的,使⽤传统事件绑定有许多缺陷,⽐如不能在⼀个对象的相同事件上注册多个事件处理函数。⽽浏览器和W3C也并⾮没有考虑到这⼀点,因此在现代浏览器中,它们有⾃⼰的⽅法绑定事件。
W3C DOM
obj.addEventListener(evtype,fn,useCapture)——W3C提供的添加事件处理函数的⽅法。obj是要添加事件的对象,evtype是事件类型,不带on前
缀,fn是事件处理函数,如果useCapture是true,则事件处理函数在捕获阶段被执⾏,否则在冒泡阶段执⾏
微软IE⽅法
obj.attachEvent(evtype,fn)——IE提供的添加事件处理函数的⽅法。obj是要添加事件的对象,evtype是事件类型,带on前缀,fn是事件处理函数,IE不⽀持事件捕获
obj.detachEvent(evtype,fn,)——IE提供的删除事件处理函数的⽅法,evtype包含on前缀
整合两者的⽅法
function addEvent(obj,evtype,fn,useCapture) {
if (obj.addEventListener) {
obj.addEventListener(evtype,fn,useCapture);
} else {
obj.attachEvent("on"+evtype,fn);//IE不⽀持事件捕获
} else {
obj["on"+evtype]=fn;//事实上这种情况不会存在
}
}
function delEvent(obj,evtype,fn,useCapture) {
if (veEventListener) {
} else {
obj.detachEvent("on"+evtype,fn);
} else {
obj["on"+evtype]=null;
}
}
IE的attach⽅法有个问题,就是使⽤attachEvent时在事件处理函数内部,this指向了window,⽽不是obj!当然,这个是有解决⽅案的!
但IE的attachEvent⽅法有另外⼀个问题,同⼀个函数可以被注册到同⼀个对象同⼀个事件上多次,解决⽅法:抛弃IE的 attachEvent⽅法吧!IE下的attachEvent⽅法不⽀持捕获,和传统事件注册没多⼤区别(除了能绑定多个事件处理函数),并且IE的 attachEvent⽅法存在内存泄漏问题!addEvent,delEvent现代版
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>js事件监听</title>
<style>
table td{font:12px; border-bottom:1px solid #efefef;}
</style>
</head>
<body>
<div id="outEle" >
<input type="button" onclick="eventfun()" id="button" value="button" /><br />
<input type="button" onclick="eventfun2(this);" id="button2" value="button2" /><br />
<input type="button" id="button3" value="button3" /><br />
<input type="button" id="button4" value="button4" /><br />
<table id="htmlEleTable" width="100%" border="0" >
<tr id="1111"><td>111111111111111111111111111111</td></tr>
<tr id="22222"><td>222222222222222222222222222222</td></tr>
<tr id="33333"><td>333333333333333333333333333333</td></tr>
<tr id="4444"><td>444444444444444444444444444444</td></tr>
<tr id="55555"><td>555555555555555555555555555555</td></tr>
</table>
</div>
<script language="javascript" type="text/javascript">
function eventfun(){//1.直接把js⽅法写在页⾯结构上
console.log(this);//这⾥涉及到⼀个this作⽤域的问题,eventfun再这⾥是⼀个全局函数, 对象是window,this指向的是window
alert(this);
}
function eventfun2(eve){//在这⾥把事件对象作为参数传递到全局⽅法⾥
eve.name="alex";//
window.name="robin";
console.log(this);//[object Window]
console.log(eve);// [object HTMLInputElement]
console.log(this.name);// robin
console.log(eve.name);// alex
var self=eve;
console.log(this.name);//robin
console.log(self.name);//alex
alert(window.name);
alert(self.name);
心跟爱一起走}
function eventfun3(){//1.直接把js⽅法写在页⾯结构上
console.log(this);//这⾥涉及到⼀个this作⽤域的问题,eventfun再这⾥是⼀个全局函数, 对象是window,this指向的是window
console.log(this.id);
alert(this);
alert(this.id);
//var outEleObj = EventUtil.$("outEle");
//removeEvent(outEleObj,"click",eventfun3);
}
/*
var EventUtil = {};
EventUtil.$ = function(id){
ElementById(id);
}
EventUtil.openmes = eventfun3;
EventUtil.addEventHandle = function(eventTarget,eventtype,eventHandle){//定义事件监听的对象元素,事件类型,事件函数
if(eventTarget.attachEvent){
eventTarget.attachEvent("on"+eventtype,eventHandle);
}else if(eventTarget.addEventListener){
eventTarget.addEventListener(eventtype,eventHandle,false)
}else{
eventTarget["on" + eventtype] = null;
}
};
EventUtil.deleEventHandle = function(eventTarget,eventtype,eventHandle){//定义事件监听的对象元素,事件类型,事件函数
if(eventTarget.detachEvent){
alert("on"+eventtype);
alert("on"+eventHandle);
eventTarget.detachEvent("on"+eventtype,eventHandle);
}else veEventListener){
}else{
eventTarget["on" + eventtype] = null;
}
};*/
var EventUtil={
$:function(id){
ElementById(id);
},
but4fun:function(){
console.log(this);
this.addEventHandle();
},
eventfun3:function (){
console.log(this);
alert(this);
delEvent(obj,evtype,fn,useCapture);
}
}
/***使⽤addEventListener,attachEvent进⾏dom事件的监听
function addEvent(obj,evtype,fn,useCapture){
if (obj.addEventListener) {
obj.addEventListener(evtype,fn,useCapture);
犬儒派}else if(obj.attachEvent){
obj.attachEvent("on"+evtype,function () {
fn.call(obj);
});
}else {
obj["on"+evtype]=fn;//事实上这种情况不会存在
}
}
function delEvent(obj,evtype,fn,useCapture) {
if (veEventListener) {
} else if(obj.detachEvent){
obj.detachEvent("on"+evtype,fn);
} else {
obj["on"+evtype]=null;
}
}
function addEvent(obj,evtype,fn,useCapture) {
if (obj.addEventListener) {//优先考虑W3C事件注册⽅案
obj.addEventListener(evtype,fn,!!useCapture);
} else {//当不⽀持addEventListener时(IE),由于IE同时也不⽀持捕获,所以不如使⽤传统事件绑定
if (!fn.__EventID) {fn.__EventID = addEvent.__EventHandlesCounter++;}
//为每个事件处理函数分配⼀个唯⼀的ID
if (!obj.__EventHandles) {obj.__EventHandles={};}
//__EventHandles属性⽤来保存所有事件处理函数的引⽤
//按事件类型分类
赵茂辰if (!obj.__EventHandles[evtype]) {//第⼀次注册某事件时
obj.__EventHandles[evtype]={};
if (obj["on"+evtype]) {//以前曾⽤传统⽅式注册过事件处理函数
(obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;//添加到预留的0位
//并且给原来的事件处理函数增加⼀个ID
}
obj["on"+evtype]=EventHandles;
//当事件发⽣时,execEventHandles遍历表obj.__EventHandles[evtype]并执⾏其中的函数
}
}
}
addEvent.__EventHandlesCounter=1;//计数器,0位预留它⽤
if (!this.__EventHandles) {return true;}
evt = evt || window.event;
var fns = this.__pe];
for (var i in fns) {
fns[i].call(this);
}
};
/*
function delEvent(obj,evtype,fn,useCapture) {
if (veEventListener) {//先使⽤W3C的⽅法移除事件处理函数
} else {
if (obj.__EventHandles) {
var fns = obj.__EventHandles[evtype];
if (fns) {delete fns[fn.__EventID];}
}
}
}
function fixEvent(evt) {//fixEvent函数不是单独执⾏的,它必须有⼀个事件对象参数,⽽且只有事件发⽣时它才被执⾏!最好的⽅法是把它整合到addEvent函数的execEventHandles⾥⾯if (!evt.target) {
evt.target = evt.srcElement;
evt.preventDefault = fixEvent.preventDefault;
evt.stopPropagation = fixEvent.stopPropagation;
if (pe == "mouseover") {
} else if (pe =="mouseout") {
}
evt.charCode = (pe=="keypress")?evt.keyCode:0;
evt.eventPhase = 2;//IE仅⼯作在冒泡阶段
evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间
}
return evt;
}
fixEvent.preventDefault =function () {
};
fixEvent.stopPropagation =function () {
this.cancelBubble = true;
};*/
//console.log(EventUtil.$("button3"));//返回EventUtil函数的对象属性
//EventUtil.$("button3").onclick= eventfun;//2.使⽤为对象事件属性赋值的⽅法来实现事件的监听
//EventUtil.$("button3").onclick= eventfun2;//为事件属性添加多个⽅法时,为后者
//EventUtil.$("button3").onclick= eventfun;//事件捕获是从事件对象逐层外⽗级检察⼀直到window对象var EventUtil =function(){
function getByid(id){
ElementById(id);
};
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini
// dean.edwards.name/weblog/2005/10/add-event/
function addEvent(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events = {};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// store the existing event handler (if there is one)
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
}
};
// a counter used to create unique IDs
addEvent.guid = 1;
function removeEvent(element, type, handler) {
if (veEventListener) {
} else {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
}
};
无缝钢轨function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event); // get a reference to the hash table of event handlers
var handlers = this.pe];
// execute each event handler
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
};
function tableAddEvent(){
};
return{
add:addEvent,
remove:removeEvent,
$:getByid
}
}();
var outEleObj = EventUtil.$("outEle");
//addEvent.apply(EventUtil,[outEleObj,"click",eventfun3]);
/
/EventUtil.add(outEleObj,"click",eventfun3);
var inputObj = EventUtil.$("button4");
var tableEle = EventUtil.$("htmlEleTable");
var tabTrEle = ElementsByTagName("tr");
EventUtil.add(tableEle,"click",eventfun3);
for (i=0; i<tabTrEle.length; i++){
EventUtil.add(tabTrEle[i],"click",eventfun3);
}
EventUtil.add(tableEle,"click",eventfun3);//事件冒泡添加⽅法
//EventUtil.add(inputObj,"click",eventfun3);
/
/ve(outEleObj,"click",eventfun3);
//console.log(addEvent);
//addEvent(inputObj,"click",eventfun3,true);
//delEvent(outEleObj,"click",eventfun3,false);
</script>
</body>
</html>
PS:这⾥再为⼤家提供⼀个关于JS事件的在线⼯具,归纳总结了JS常⽤的事件类型与函数功能:javascript事件与功能说明⼤全:

本文发布于:2024-09-21 11:04:03,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/516674.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:事件   对象   函数   元素
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议