事件捕获,javascript快速入门17
分类:计算机网络

<!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=utf-8" /> 
<title>js事件监听</title> 
<style> 
table td{font:12px; border-bottom:1px solid #efefef;} 
</style> 
</head> 

<body> 
<div id="outEle" style="padding:10px; border:1px solid #b2b2b2; background:#efefef;"> 
<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" style="border:1px solid #b2b2b2; background:#fff;"> 
<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){ 
return document.getElementById(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 if(eventTarget.removeEventListener){ 
eventTarget.removeEventListener(eventtype,eventHandle,false) 
}else{ 
eventTarget["on" + eventtype] = null; 
} 

};*/ 
var EventUtil={ 
$:function(id){ 
return document.getElementById(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 (obj.removeEventListener) { 
obj.removeEventListener(evtype,fn,useCapture); 
} 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]=addEvent.execEventHandles; 
//当事件发生时,execEventHandles遍历表obj.__EventHandles[evtype]并执行其中的函数 
} 
} 
} 

addEvent.__EventHandlesCounter=1;//计数器,0位预留它用 
addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行 
if (!this.__EventHandles) {return true;} 
evt = evt || window.event; 
var fns = this.__EventHandles[evt.type]; 
for (var i in fns) { 
fns[i].call(this); 
} 
}; 
/* 
function delEvent(obj,evtype,fn,useCapture) { 
if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数 
obj.removeEventListener(evtype,fn,!!useCapture); 
} 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 (evt.type == "mouseover") { 
evt.relatedTarget = evt.fromElement; 
} else if (evt.type =="mouseout") { 
evt.relatedTarget = evt.toElement; 
} 
evt.charCode = (evt.type=="keypress")?evt.keyCode:0; 
evt.eventPhase = 2;//IE仅工作在冒泡阶段 
evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间 
} 
return evt; 
} 
fixEvent.preventDefault =function () { 
this.returnValue = false;//这里的this指向了某个事件对象,而不是fixEvent 
}; 
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){ 
return document.getElementById(id); 
}; 
// written by Dean Edwards, 2005 
// with input from Tino Zijdel, Matthias Miller, Diego Perini 

// http://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 (element.removeEventListener) { 
element.removeEventListener(type, handler, false); 
} 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.events[event.type]; 
// 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() { 
this.returnValue = false; 
}; 
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 = tableEle.getElementsByTagName("tr"); 
EventUtil.add(tableEle,"click",eventfun3); 
for (i=0; i<tabTrEle.length; i++){ 
EventUtil.add(tabTrEle[i],"click",eventfun3); 
} 
EventUtil.remove(tableEle,"click",eventfun3);//事件冒删除方法 
EventUtil.add(tableEle,"click",eventfun3);//事件冒泡添加方法 
//EventUtil.add(inputObj,"click",eventfun3); 
//EventUtil.remove(outEleObj,"click",eventfun3); 
//console.log(addEvent); 
//addEvent(inputObj,"click",eventfun3,true); 
//delEvent(outEleObj,"click",eventfun3,false); 
</script> 
</body> 
</html>

js的监听事件

<table id="table_id">
<tr>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
</tr>
<tr>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
</tr>
<tr>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
</tr>
<tr>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
<td><p>1,1</p></td>
</tr>
</table>
<p>kkkkkkkkkk</p>
<script type="text/javascript">
var tb=document.getElementById('table_id') //获取到这几个table,用别的方法也能够
ps=tb.getElementsByTagName("p"),
trs=tb.getElementsByTagName("tr")

trs.index=function(tr){
for(var i=0;i<this.length;i++){
if(this[i]===tr)return i
}
}

for(var i=0;i......余下全文>>  

在前端开荒进度中大家经常会遇见给页面成分增加事件的标题,增添风云的js方法也相当多,有直接加...

在JavaScript中,DOM2级事件规定的小运流满含八个等第:

冒泡事件流

当事件在某一DOM成分被触发时,譬如客商在顾客名字节点上点击鼠标,事件将随行着该节点承继自的逐个父节点冒泡穿过整个的DOM节点档案的次序,直到它境遇依靠有该事件类型管理器的节点,此时,该事件是onclick事件。在冒泡进程中的任哪天候都足以告一段落事件的冒泡,在坚守W3C标准的浏览器里能够通过调用事件指标上的stopPropagation()方法,在Internet Explorer里能够经过设置事件指标的cancelBubble属性为true。假若不结束事件的传入,事件将平素通过DOM冒泡直至达到文书档案根。

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 (obj.removeEventListener) { 
obj.removeEventListener(evtype,fn,useCapture); 
} else { 
obj.detachEvent("on"+evtype,fn); 
} else { 
obj["on"+evtype]=null; 
} 
}

js事件监听

<input type="button" value="connect" onclick="a()" />
<script>function a() {alert(1);}</script>  

(1)事件捕获阶段

 (2)处于目的阶段

 (3)事件冒泡阶段

今世事件绑定方法

本着如上节课所商议的,使用古板事件绑定有众多缺点,举个例子无法在三个指标的同样事件上登记多个事件管理函数。而浏览器和W3C也不用未有思索到这点,因而在今世浏览器中,它们有和睦的主意绑定事件。

W3C DOM

  • obj.addEventListener(evtype,fn,useCapture)——W3C提供的丰盛事件管理函数的格局。obj是要增多事件的对象,evtype是事件类型,不带on前缀,fn是事件管理函数,倘若useCapture是true,则事件管理函数在抓获阶段被施行,不然在冒泡阶段施行
  • obj.remove伊芙ntListener(evtype,fn,useCapture)——W3C提供的删除事件管理函数的措施

微软IE方法

  • obj.attachEvent(evtype,fn)——IE提供的丰裕事件处理函数的方法。obj是要足够事件的对象,evtype是事件类型,带on前缀,fn是事件管理函数,IE不援助事件捕获
  • obj.detach伊夫nt(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 (obj.removeEventListener) {
            obj.removeEventListener(evtype,fn,useCapture);
        } else {
            obj.detachEvent("on"+evtype,fn);
        } else {
            obj["on"+evtype]=null;
        }
    }

 

另外包容性难点:IE不帮助事件捕获?很对不起,那一个未有主意化解!但IE的attach方法有个难题,正是行使attach伊芙nt时在事件管理函数内部,this指向了window,并不是obj!当然,那些是有消除方案的!

    function addEvent(obj,evtype,fn,useCapture) {
        if (obj.addEventListener) {
            obj.addEventListener(evtype,fn,useCapture);
        } else {
            obj.attachEvent("on"+evtype,function () {
                fn.call(obj);
            });
        } else {
            obj["on"+evtype]=fn;//事实上这种情况不会存在
        }
    }

 

但IE的attachEvent方法有别的一个标题,同贰个函数能够被注册到同三个目的同贰个平地风波上多次,解决方法:丢掉IE的attach伊夫nt方法吗!IE下的attachEvent方法不帮忙捕获,和价值观事件注册没多大不同(除了能绑定多少个事件管理函数),何况IE的attachEvent方法存在内部存款和储蓄器泄漏难点!

addEvent,delEvent现代版

    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]=addEvent.execEventHandles;
                //当事件发生时,execEventHandles遍历数组obj.__EventHandles[evtype]并执行其中的函数
            }
        }
    }
    addEvent.__EventHandlesCounter=1;//计数器,0位预留它用
    addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行
        if (!this.__EventHandles) {return true;}
        evt = evt || window.event;
        var fns = this.__EventHandles[evt.type];
        for (var i=0;i< fns.length;i++) {
            if (fns[i] instanceof Function) {
                fns[i].call(this);
            }
        }
    };
    function delEvent(obj,evtype,fn,useCapture) {
        if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数
            obj.removeEventListener(evtype,fn,!!useCapture);
        } else {
            if (obj.__EventHandles) {
                var fns = obj.__EventHandles[evtype];
                if (fns) {delete fns[fn.__EventID];}
            }
        }
    }

 

在前端开荒进程中大家日常会遇见给页面成分增加事件的主题材料,增添事件的js方法也很多,有平昔加到页面结构上的,有应用一些js事件监听的章程,由于各种浏览器对事件冒泡事件监听的机制分裂,le浏览器唯有事件冒泡,未有事件监听的体制,对于事件监听的包容性难题是最大的难点:

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. 利用给事件性质赋值的措施,是一种为事件绑定的艺术,但是这种方法的局限性正是不得不为事件绑定三个主意,即便绑定多个就能够将来三个措施为准

HTMLElementobject.onclick = fucntion(){//使用这种为事件性质赋值的主意,this的指针会指向window对象,并不是被事件指标,所以这种艺术是引用

//js code 
fun1(); 
fun2(); 
fun3(); 
console.log(this);//window.object 
} 
function dosomething(){ 
//js code 
} 
HTMLElementobject.onclick = dosomething;//使用这种为事件对象属性赋值的形式,this指针指向事件执行对象 
console.log(this);//htmlElementObject

3.事件传播——冒泡与捕获
DOM事件标准定义了二种事件流,那二种事件流有所刚烈的例外何况或者对你的运用具备一定大的影响。这两种事件流分别是捕获和冒泡。和好多Web技巧同样,在它们变成标准以前,Netscape和微软独家不一致地完成了它们。Netscape选拔实现了捕获事件流,微软则贯彻了冒泡事件流。幸运的 是,W3C决定结合使用那三种情势,而且大许多新浏览器都服从这两种事件流格局。
暗中同意意况下,事件接纳冒泡事件流,不行使捕获事件流。然则,在Firefox和Safari里,你能够显式的钦点使用捕获事件流,方法是在登记事件时传出useCapture参数,将以此参数设为true。
冒泡事件流
当事件在某一DOM成分被触发时,举个例子顾客在客商名字节点上点击鼠标,事件将跟随着该节点承袭自的次第父节点冒泡穿过整个的DOM节点档次,直到它 遭受依赖有该事件类型管理器的节点,此时,该事件是onclick事件。在冒泡进程中的任曾几何时候都得以告一段落事件的冒泡,在依照W3C规范的浏览器里可以通 过调用事件目的上的stopPropagation()方法,在Internet Explorer里能够因而设置事件指标的cancelBubble属性为true。假设不鸣金收兵事件的传播,事件将直接通过DOM冒泡直至到Dawen档根。
抓获事件流
事件的拍卖将从DOM档次的根早先,而不是从触发事件的对象成分初阶,事件被从指标成分的装有祖先成分依次往下传递。在那一个历程中,事件会被从文书档案根到事件目的成分之间顺次承继派生的要素所破获,如若事件监听器在被登记时设置了useCapture属性为true,那么它们得以被分派给这里面包车型客车别样 成分以对事件做出管理;不然,事件会被随后传递给派生成分路线上的下一成分,直至指标成分。事件到达指标成分后,它会跟着通过DOM节点再拓宽冒泡。
今世事件绑定方法
本着如上节课所商讨的,使用传统事件绑定有数不清欠缺,举个例子无法在三个指标的一致事件上登记八个事件管理函数。而浏览器和W3C也毫无未有思量到那或多或少,由此在现世浏览器中,它们有友好的方法绑定事件。
W3C DOM
obj.addEventListener(evtype,fn,useCapture)——W3C提供的拉长事件管理函数的措施。obj是要增加事件的对象,evtype是事件类型,不带on前缀,fn是事件管理函数,要是useCapture是true,则事件管理函数在抓获阶段被实践,否则在冒泡阶段实施
obj.remove伊夫ntListener(evtype,fn,useCapture)——W3C提供的去除事件管理函数的点子
微软IE方法
obj.attach伊芙nt(evtype,fn)——IE提供的增加事件管理函数的艺术。obj是要拉长事件的对象,evtype是事件类型,带on前缀,fn是事件管理函数,IE不支持事件捕获
obj.detach伊芙nt(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 (obj.removeEventListener) { 
obj.removeEventListener(evtype,fn,useCapture); 
} else { 
obj.detachEvent("on"+evtype,fn); 
} else { 
obj["on"+evtype]=null; 
} 
}

IE的attach方法有个难题,便是行使attachEvent时在事件管理函数内部,this指向了window,并不是obj!当然,那么些是有缓和方案的!

但IE的attach伊夫nt方法有别的一个难题,同贰个函数可以被登记到同一个对象同一个事变上每每,消除办法:甩掉IE的 attachEvent方法吧!IE下的attach伊夫nt方法不援助捕获,和历史观事件注册没多大分别(除了能绑定七个事件管理函数),况且IE的 attachEvent方法存在内部存款和储蓄器泄漏难题!
addEvent,delEvent现代版

<!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=utf-8" /> 
<title>js事件监听</title> 
<style> 
table td{font:12px; border-bottom:1px solid #efefef;} 
</style> 
</head> 

<body> 
<div id="outEle" style="padding:10px; border:1px solid #b2b2b2; background:#efefef;"> 
<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" style="border:1px solid #b2b2b2; background:#fff;"> 
<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){ 
return document.getElementById(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 if(eventTarget.removeEventListener){ 
eventTarget.removeEventListener(eventtype,eventHandle,false) 
}else{ 
eventTarget["on" + eventtype] = null; 
} 

};*/ 
var EventUtil={ 
$:function(id){ 
return document.getElementById(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 (obj.removeEventListener) { 
obj.removeEventListener(evtype,fn,useCapture); 
} 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]=addEvent.execEventHandles; 
//当事件发生时,execEventHandles遍历表obj.__EventHandles[evtype]并执行其中的函数 
} 
} 
} 

addEvent.__EventHandlesCounter=1;//计数器,0位预留它用 
addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行 
if (!this.__EventHandles) {return true;} 
evt = evt || window.event; 
var fns = this.__EventHandles[evt.type]; 
for (var i in fns) { 
fns[i].call(this); 
} 
}; 
/* 
function delEvent(obj,evtype,fn,useCapture) { 
if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数 
obj.removeEventListener(evtype,fn,!!useCapture); 
} 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 (evt.type == "mouseover") { 
evt.relatedTarget = evt.fromElement; 
} else if (evt.type =="mouseout") { 
evt.relatedTarget = evt.toElement; 
} 
evt.charCode = (evt.type=="keypress")?evt.keyCode:0; 
evt.eventPhase = 2;//IE仅工作在冒泡阶段 
evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间 
} 
return evt; 
} 
fixEvent.preventDefault =function () { 
this.returnValue = false;//这里的this指向了某个事件对象,而不是fixEvent 
}; 
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){ 
return document.getElementById(id); 
}; 
// written by Dean Edwards, 2005 
// with input from Tino Zijdel, Matthias Miller, Diego Perini 

// http://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 (element.removeEventListener) { 
element.removeEventListener(type, handler, false); 
} 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.events[event.type]; 
// 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() { 
this.returnValue = false; 
}; 
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 = tableEle.getElementsByTagName("tr"); 
EventUtil.add(tableEle,"click",eventfun3); 
for (i=0; i<tabTrEle.length; i++){ 
EventUtil.add(tabTrEle[i],"click",eventfun3); 
} 
EventUtil.remove(tableEle,"click",eventfun3);//事件冒删除方法 
EventUtil.add(tableEle,"click",eventfun3);//事件冒泡添加方法 
//EventUtil.add(inputObj,"click",eventfun3); 
//EventUtil.remove(outEleObj,"click",eventfun3); 
//console.log(addEvent); 
//addEvent(inputObj,"click",eventfun3,true); 
//delEvent(outEleObj,"click",eventfun3,false); 
</script> 
</body> 
</html>

微软IE方法

        obj.attach伊夫nt(evtype,fn)——IE提供的丰硕事件管理函数的艺术。obj是要抬高事件的指标,evtype是事件类型,带on前缀,fn是事件管理函数,IE不帮衬事件捕获obj.detachEvent(evtype,fn,)——IE提供的删除事件管理函数的方法,evtype满含on前缀。

访谈事件指标:W3C DOM方法与IE专项使用方法

    //W3C DOM把事件对象作为事件处理函数的第一个参数传入进去
    document.onclick = function (evt) {//这样,事件对象只能在对应的事件处理函数内部可以访问到
        alert(evt);
    };
    //IE将事件对象作为window对象的一个属性(相当于全局变量)
    //貌似全局对象,但是只有是事件发生时才能够访问
    alert(window.event);//null
    window.onload = function () {
        alert(window.event);
    };

 

事件指标的特性及措施

鼠标相关
属性名 值类型 读/写 描述
button Integer R

对于特定的鼠标事件,表示按下的鼠标按钮,该属性仅可以在mouseup与mousedown事件中访问。W3C 规定:0表示按下了左键,1表示按下了中键,2表示按下了右键,相当于对于鼠标键从左到右进行的编号,而编号从0开始; 而IE有另外一套规定:0表示没有任何键按下,1表示左键,2表示右键,4表示中键,而其它按键的组合则只要将键码相加即可,如:同时按下左右键时button值为3

clientX Integer R 事件发生时,鼠标在客户端区域的X坐标,客户端区域是指页面可视区域
clientY Integer R 事件发生时,鼠标在客户端区域的Y坐标
screenX Integer R(IE)
R/W(W3C)
相对于屏幕的鼠标X坐标
screenY Integer R(IE)
R/W(W3C)
相对于屏幕的鼠标Y坐标
x(仅IE) Integer R 鼠标相对于引起事件的元素的父元素的X坐标
y(仅IE) Integer R 鼠标相对于引起事件的元素的父元素的Y坐标
offsetX(仅IE)
layerX(仅W3C)
Integer R 鼠标相对于引起事件的对象的X坐标
offsetY(仅IE)
layerY(仅W3C)
Integer R 鼠标相对于引起事件的对象的Y坐标
pageX(仅W3C) Integer R 鼠标相对于页面的X坐标
pageY(仅W3C) Integer R 鼠标相对于页面的Y坐标

 

键盘相关
属性名 值类型 读/写 描述
altKey Boolean R true表示按下了ALT键;false表示没有按下
ctrlKey Boolean R true表示按下了CTROL,false表示没有
shiftKey Boolean R true表示按下了shift,false表示没有
keyCode Integer R/W(IE)
R(W3C)
对于keypress事件,表示按下按钮的Unicode字符;对于keydown/keyup事件 ,表示按下按钮的数字代号
charCode(仅W3C) Integer R 在keypress事件中所按键的字符Unicode编码,如果不是字符键,则该属性为0,并且,当CapsLock打开与关闭时charCode的值也对应着大小写字母

 其它

属性名 值类型 读/写 描述
srcElement(IE)
target(W3C)
Element R 引起事件的元素
fromElement(仅IE) Element R 某些鼠标事件中(mouseover与mouseout),鼠标所离开的元素
toElement(仅IE) Element R 某些鼠标事件中(mouseover与mouseout),鼠标所进入的元素
relatedTarget(仅W3C) Element R 某些鼠标事件中(mouseover与mouseout),返回与事件的目标节点相关的节点。
repeat(仅IE) Boolean R 如果不断触发keydown事件,则为true,否则为false
returnValue(仅IE) Boolean R/W 将其设为false表示以取消事件的默认动作
preventDefault(仅W3C) Function R 执行方法以取消事件的默认动作
type String R 事件的名称,不带on前缀
cancelable(仅W3C ) Boolean R 当为true表示事件的默认动作可以被取消(用preventDefault方法取消)
cancelBubble(仅IE) Boolean R/W 将其设置为true将取消事件冒泡
stopPropagation(仅W3C) Function R 执行方法取消事件冒泡
bubbles(仅W3C) Boolean R 返回true表示事件是冒泡类型
eventPhase(仅W3C) Integer R 返回事件传播的当前阶段。它的值是下面的三个常量之一,它们分别表示捕获阶段、在目标对象上时和起泡阶段:
常量
Event.CAPTURING_PHASE(捕获阶段) 1
Event.AT_TARGET(在目标对象上) 2
Event.BUBBLING_PHASE(冒泡阶段) 3
timeStamp (仅W3C) Long R 返回一个时间戳。指示发生事件的日期和时间(从 epoch 开始的毫秒数)。epoch 是一个事件参考点。在这里,它是客户机启动的时间。并非所有系统都提供该信息,因此,timeStamp 属性并非对所有系统/事件都是可用的。

收获事件目的及获得事件指标对象

    document.onclick =function (evt) {
        evt = evt || window.event;//在IE中evt会是undefined
        //而支持W3C DOM事件的浏览器中事件对象将会作为事件处理函数的第一个参数
        var targetElement = evt.target || evt.srcElement;
        //IE中事件对象没有target属性
    };

 

阻碍事件时有产生时浏览器的暗许行为

    document.onclick = function (evt) {
        evt = evt || window.event;
        var target = evt.target || evt.srcElement;
        if (!target) {
            return;
        }
        if (target.tagName=="A" && target.href) {
            //使用传统的方法取消事件默认行为必须使用return false
            //但使用了return ,函数便终止了运行,可以使用事件对象来取消
            if (window.event) {//IE
                window.event.returnValue = false;
            } else {
                evt.preventDefault();
            }
            window.open(target.href,"newWindow");
            //这样让所有的链接在新窗口打开
        }
    };
//js code 
fun1(); 
fun2(); 
fun3(); 
console.log(this);//window.object 
} 
function dosomething(){ 
//js code 
} 
HTMLElementobject.onclick = dosomething;//使用这种为事件对象属性赋值的形式,this指针指向事件执行对象 
console.log(this);//htmlElementObject

W3CDOM

       obj.addEventListener(evtype,fn,useCapture)——W3C提供的增加事件管理函数的议程。obj是要增添事件的对象,evtype是事件类型,不带on前缀,fn是事件管理函数,若是useCapture是true,则事件管理函数在抓获阶段被实施,不然在冒泡阶段实践obj.removeEventListener(evtype,fn,useCapture)——W3C提供的删除事件管理函数的方法

事件(下)

要缓慢解决this功能域的难点,能够行使为全局函数增添event变量的秘技,在页面结构大校this对象作为参数字传送递到函数内部采取

事件传播——冒泡与捕获

        DOM事件规范定义了二种事件流,这二种事件流有所显明的分化何况恐怕对你的利用具备一定大的熏陶。那三种事件流分别是捕获和冒泡。和重重Web本领一样,在它们产生专门的工作之前,Netscape和微软独家分裂地落到实处了它们。Netscape选取完毕了捕获事件流,微软则贯彻了冒泡事件流。幸运的 是,W3C决定结合使用那三种方法,並且大多数新浏览器都遵循那三种事件流格局。

       大比很多情景下,事件采取冒泡事件流,不利用捕获事件流。可是,在Firefox和Safari里,你能够显式的钦赐使用捕获事件流,方法是在注册事件时传出useCapture参数,将以此参数设为true。

事件(上)

JavaScript事件列表

事件

解说

相似事件

onclick

鼠标点击时触发那件事件

ondblclick

鼠标双击时触发那件事件

onmousedown

按下鼠标时触发那一件事件

onmouseup

鼠标按下后松手鼠标时触发这件事件

onmouseover

当鼠标移动到某指标限定的上方时触发这件事件

onmousemove

鼠标移动时触发那件事件

onmouseout

当鼠标离开某目的限定期触发那一件事件

onkeypress

当键盘上的某部键被按下同时释放时触发那一件事件.

onkeydown

当键盘上某些开关被按下时触发那一件事件

onkeyup

当键盘上有些按钮被按松开时触发那件事件

页面相关事件

onabort

图形在下载时被客户中断

onbeforeunload

脚下页面包车型地铁内容就要被退换时触发那一件事件

onerror

并发谬误时触发那一件事件

onload

页面内容达成时触发那一件事件

onmove

浏览器的窗口被移位时触发这件事件

onresize

当浏览器的窗口大小被退换时触发那一件事件

onscroll

浏览器的滚动条地点发生变化时触发那件事件

onstop

浏览器的结束按键被按下时触发那件事件恐怕正在下载的文件被中断

oncontextmenu

当弹出右键上下文菜单时发生

onunload

现阶段页面将被改换时触发这件事件

表单相关事件

onblur

近年来成分失去核心时触发此事件

onchange

脚下成分失去大旨并且成分的内容产生改造而触发那件事件

onfocus

当有个别成分得到大旨时触发那事件

onreset

当表单中RESET的属性被激励时触发那件事件

onsubmit

多少个表单被递交时触发那件事件

询问上边包车型地铁风浪如此回顾,那么事件还也是有啥样可讲的吗?

难点一:每一种事件只好登记一个函数

    var oDiv = document.getElementById("oDiv");
    oDiv.onclick = fn1;
    oDiv.onclick =fn2;
    function fn1() {alert("我被覆盖了!")}
    function fn2() {alert("只有我被执行到!")}

 

杀鸡取蛋方案一:

    obj.onclick = function () {
        fn1();
        fn2();
        fn3();
    };

 

缺陷一:供给将具有函数叁次增加进去,无法在运作时增加

症结二:在事件管理函数中this将针对window,实际不是obj

消除方案二:

    function addEvent(fn,evtype,obj) {
        //obj是要添加事件的HTML元素对象
        //evtype是事件名字,不包含on前缀,因为每个都有on,所以写个on是多余的
        //fn是事件处理函数
        var oldFn;
        if (obj["on"+evtype] instanceof Function) {
            oldFn = obj["on"+evtype];//当添加函数时,如果已注册过了,则将其保存起来
        }
        obj["on"+evtype]=function () {
                if (oldFn) {
                    oldFn.call(this);
                }
                fn.call(this);//使用call方法,使事件处理函数中的this仍指向obj
        };
    }

 

那般已经缓和了难点,但怎样删除事件呢?若是一直将目的的onevtype那类的质量赋值为null将会删除全数的事件处理函数!

缓和方案二的修改版:先将事件存款和储蓄起来,存款和储蓄在对象的__EventHandles属性里面

    eventHandlesCounter=1;//计数器,将统计所有添加进去的函数的个数,0位预留作其它用
    function addEvent(fn,evtype,obj) {
        if (!fn.__EventID) {//__EventID是给函数加的一个标识,见下面给函数添加标识的部分
            fn.__EventID=eventHandlesCounter++;
            //使用一个自动增长的计数器作为函数的标识以保证不会重复
        }
        if (!obj.__EventHandles) {
            obj.__EventHandles=[];//当不存在,也就是第一次执行时,创建一个,并且是数组
        }
        if (!obj.__EventHandles[evtype]) {//将所有事件处理函数按事件类型分类存放
            obj.__EventHandles[evtype]=[];//当不存在时也创建一个数组
            if (obj["on"+evtype] instanceof Function) {
                //查看是否已经注册过其它函数
                //如果已经注册过,则将以前的事件处理函数添加到数组下标为0的预留的位置
                obj.__EventHandles[evtype][0]=obj["on"+evtype];
                obj["on"+evtype]=handleEvents;//使用handleEvents集中处理所有的函数
            }
        }
        obj.__EventHandles[evtype][fn.__EventID]=fn;
        //如果函数是第一次注册为事件处理函数,那么它将被添加到数组中,函数的标识作为下标
        //如果函数已经注册过相同对象的相同事件了,那么将覆盖原来的而不会被添加两次
        function handleEvents() {
            var fns = obj.__EventHandles[evtype];
            for (var i=0;i< fns.length;i++) {
                fns[i].call(this);
            }
        }
    }

 

应用方面包车型地铁函数已经能够在贰个对象增多多少个事件管理函数,在函数内部this关键字也本着了相应的靶子,并且那个函数都被作了标记,那么移除某些事件管理函数便是一下子就化解了的了!

    //使用传统方法:obj.onevtype = null;但这样会移除所有的事件处理函数
    function delEvent(fn,evtype,obj) {
        if (!obj.__EventHandles || !obj.__EventHandles[evtype] || !fn.__EventID) {
            return false;
        }
        if (obj.__EventHandles[evtype][fn.__EventID] == fn) {
            delete obj.__EventHandles[evtype][fn.__EventID];
        }
    }

 

javascript事件与功用表达大全:

抓获事件流

       事件的拍卖将从DOM档次的根伊始,并不是从触发事件的靶子成分伊始,事件被从目的成分的具有祖先元素依次往下传递。在那几个进度中,事件会被从文书档案根到事件目的成分之间顺次承继派生的因素所擒获,假如事件监听器在被登记时设置了useCapture属性为true,那么它们得以被分派给那中间的任何 成分以对事件做出管理;否则,事件会被随后传递给派生成分路线上的下一成分,直至目的成分。事件达到指标成分后,它会跟着通过DOM节点再开展冒泡。

抓获事件流

事件的管理将从DOM等级次序的根起先,并不是从触发事件的目的成分开头,事件被从目的成分的兼具祖先成分依次往下传递。在那些进度中,事件会被从文书档案根到事件指标成分之间顺次承接派生的要素所抓获,借使事件监听器在被登记时设置了useCapture属性为true,那么它们得以被分派给那时期的别的因素以对事件做出管理;不然,事件会被随后传递给派生成分路线上的下一成分,直至目的成分。事件到达目的成分后,它会随着通过DOM节点再实行冒泡。

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,则事件处理函数在捕获阶段被推行,不然在冒泡阶段施行
obj.removeEventListener(evtype,fn,useCapture)——W3C提供的删减事件管理函数的方法
微软IE方法
obj.attachEvent(evtype,fn)——IE提供的充足事件管理函数的秘技。obj是要加多事件的靶子,evtype是事件类型,带on前缀,fn是事件管理函数,IE不支持事件捕获
obj.detachEvent(evtype,fn,)——IE提供的去除事件管理函数的方法,evtype满含on前缀

removeEventHandler:移除Dom成分的风云

target:监听指标; type:监听函数类型,如click,mouseover;func:监听函数。

图片 1

事件目的——伊夫nt

事件目的是用来记录一些风云发生时的连带消息的靶子。事件指标只有事件发生时才会时有发生,而且只可以是事件管理函数内部访问,在装有事件管理函数运转截止后,事件目标就被灭绝!

您或然感兴趣的稿子:

  • js自定义事件及事件交互原理概述(一)
  • JavaScript自定义事件介绍
  • 详解javascript达成自定义事件
  • js自定义事件及事件交互原理概述(二)
  • javascript 自定义事件初探
  • js自定义事件代码表明
  • 谈一谈JS音信机制和事件机制的明白
  • 深深分析JavaScript框架Backbone.js中的事件机制
  • 深远领会JS DOM事件机制
  • 运用Javascript达成一套自定义事件机制

事件机制的阻拦

阻挡事件冒泡:stopPropagation();

掣肘事件的破获:DOM3级新添事件stopImmediatePropagation();**

这么些正是最基本的事件机制的历程!!

www.jb51.net/article/53438.htm

Load事件

运用JavaScript垄断(monopoly)DOM,必须等待DOM加载实现才得以实践代码,但window.onload有个坏处,它非要等到页面中的全体图片及录像加载达成才会触发load事件。结果正是一些理所必然应该在开采时遮掩起来的因素,由于互联网延迟,在页面张开时依旧会师世,然后又会猝然熄灭,让顾客以为莫明其妙。必得与这种丑陋的闪光拜别!

    function addLoadEvent(fn) {
        var init = function() {
            if (arguments.callee.done) return;
            arguments.callee.done = true;
            fn.apply(document,arguments);
        };
        //注册DOMContentLoaded事件,如果支持的话
        if (document.addEventListener) {
            document.addEventListener("DOMContentLoaded", init, false);
        }
        //但对于Safari,我们需要使用setInterval方法不断检测document.readyState
        //当为loaded或complete的时候表明DOM已经加载完毕
        if (/WebKit/i.test(navigator.userAgent)) {
            var _timer = setInterval(function() {
                if (/loaded|complete/.test(document.readyState)) {
                    clearInterval(_timer);
                    init();
                }
            },10);
        }
        //对于IE则使用条件注释,并使用script标签的defer属性
         //IE中可以给script标签添加一个defer(延迟)属性,这样,标签中的脚本只有当DOM加载完毕后才执行
         /*@cc_on @*/
         /*@if (@_win32)
         document.write("<script id="__ie_onload" defer="defer" src="javascript:void(0)"></script>");
         var script = document.getElementById("__ie_onload");
         script.onreadystatechange = function() {
             if (this.readyState == "complete") {
                 init();
             }
         };
         /*@end @*/
         return true;
     }

 

2. 用到给事件性质赋值的法门,是一种为事件绑定的章程,不过这种措施的局限性正是不得不为事件绑定一个方式,倘使绑定四个就能够未来一个方法为准

add伊夫ntListener:监听Dom成分的事件

target:监听目的; type:监听函数类型,如click,mouseover;func:监听函数。

图片 2

条件事件指标

IE的事件目的与W3C DOM的风浪指标有无数不雷同的地点,消除的最棒的方法便是调动IE的轩然大波目的,以使它尽大概的与正统一般!下表列出了IE事件目的中部分和W3C DOM名称或值差别等但意义一样的习性

IE与W3C DOM事件对象的不同
W3C DOM IE
button——按键编码为:0-左键,1-中键,2-右键 button——按键编码为:1-左键,2-右键,4-中键
charCode 没有对应属性,但可以用keyCode来代替
preventDefault 没有对应方法,但可以将event对象的returnValue设为false来模拟
target srcElement
relatedTarget fromElement与toElement
stopPropagation 没有对应方法,但可以通过将event对象的cancelBubble属性设为true来模拟

总结出fixEvent函数

    function fixEvent(evt) {
        if (!evt.target) {
            evt.target = evt.srcElement;
            evt.preventDefault = fixEvent.preventDefault;
            evt.stopPropagation = fixEvent.stopPropagation;
            if (evt.type == "mouseover") {
                evt.relatedTarget = evt.fromElement;
            } else if (evt.type =="mouseout") {
                evt.relatedTarget = evt.toElement;
            }
            evt.charCode =  (evt.type=="keypress")?evt.keyCode:0;
            evt.eventPhase = 2;//IE仅工作在冒泡阶段
            evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间
        }
        return evt;
    }
    fixEvent.preventDefault =function () {
        this.returnValue = false;//这里的this指向了某个事件对象,而不是fixEvent
    };
    fixEvent.stopPropagation =function () {
        this.cancelBubble = true;
    };

 

fixEvent函数不是独立实践的,它必需有三个风浪目的参数,而且只有事件时有爆发时它才被实施!最佳的格局是把它结合到add伊夫nt函数的execEventHandles里面

    addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行
        if (!this.__EventHandles) {return true;}
        evt = fixEvent(evt || window.event);//在这里对其进行标准化操作
        var fns = this.__EventHandles[evt.type];
        for (var i=0;i< fns.length;i++) {
            if (fns[i] instanceof Function) {
                fns[i].call(this,evt);//并且将其作为事件处理函数的第一个参数
                //这样在事件处理函数内部就可以使用统一的方法访问事件对象了
            }
        }
    };

 

结合双方的办法

冒泡事件流  

        当事件在某一DOM成分被触发时,比方用户在客商名字节点上点击鼠标,事件将跟随着该节点承袭自的顺序父节点冒泡穿过整个的DOM节点档期的顺序,直到它境遇凭仗有该事件类型处理器的节点,此时,该事件是onclick事件。在冒泡进程中的任何时候都足以告一段落事件的冒泡,在服从W3C标准的浏览器里能够通 过调用事件目的上的stopPropagation()方法,在Internet Explorer里能够通过安装事件指标的cancelBubble属性为true。要是不结束事件的突然不见了,事件将直接通过DOM冒泡直至达到文书档案根。

事件传播——冒泡与捕获

DOM事件标准定义了二种事件流,那三种事件流有所鲜明的不等何况或许对您的选择具有极大的影响。这三种事件流分别是捕获和冒泡。和广大Web技巧一样,在它们成为标准在此以前,Netscape和微软各自区别地促成了它们。Netscape选拔实现了捕获事件流,微软则完成了冒泡事件流。幸运的是,W3C决定整合使用那二种艺术,並且大好些个新浏览器都依照那三种事件流方式。

暗许境况下,事件接纳冒泡事件流,不应用捕获事件流。可是,在Firefox和Safari里,你能够显式的钦命使用捕获事件流,方法是在登记事件时传出useCapture参数,将那些参数设为true。

但IE的attachEvent方法有另外三个标题,同叁个函数能够被注册到同多少个指标同三个事件上数十二次,消除方法:放任IE的 attach伊夫nt方法呢!IE下的attachEvent方法不扶助捕获,和古板事件注册没多大分别(除了能绑定三个事件管理函数),并且IE的 attachEvent方法存在内部存款和储蓄器泄漏难点!
addEvent,delEvent现代版

<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); 
}

1.直接把事件的法子写在页面结构上

HTMLElementobject.onclick = fucntion(){//使用这种为事件性质赋值的章程,this的指针会指向window对象,并非被事件目的,所以这种措施是援用

PS:这里再为大家提供二个关于JS事件的在线工具,归结总括了JS常用的风云类型与函数效率:

IE的attach方法有个难点,就是运用attach伊芙nt时在事件管理函数内部,this指向了window,实际不是obj!当然,这么些是有缓和方案的!

function eventfun(){ 
//console.log(this); 
} 
<input type="button" onclick="eventfun()" value="button" />//这里涉及到一个this作用域的问题,eventfun再这里是一个全局函数, 对象是[object Window],this指向的是window.

本文由美高梅网址发布于计算机网络,转载请注明出处:事件捕获,javascript快速入门17

上一篇:基于JavaScript实现简单的随机抽奖小程序,javasc 下一篇:追加元素append,方法的区别及使用介绍
猜你喜欢
热门排行
精彩图文