谈谈JavaScript事件

众所周知,web前端包含三个基本技术:html、css和javascript。三者融合,才让网页变得精彩纷呈!如今,web上的操作越来越趋于复杂,JavaScript事件在网页中也遍地开花,有时候也是遍地生Bug。真正理解了JavaScript的事件模型,才能在实际开发中佛挡杀佛,bug挡杀bug。

前言

这是我自己对JavaScript事件模型的理解,并且参考了网络上的各家之言。由于本人才疏学浅,难免有错误之处,还望指正。
在工作学习中,你或许不知道见过多少事件了。那么,到底什么是JavaScript事件呢?我们先来运行一段代码:

var out = [];
for ( var i in window) {
  if ( /^on/.test(i)) { out[out.length] = i; }
}
console.log(out);

是不是看到了如下一大串东西(我是在chrome中运行的)?

["onautocompleteerror", "onautocomplete", "ondeviceorientation", "ondevicemotion", "onunload", "onstorage", "onpopstate", "onpageshow", "onpagehide", "ononline", "onoffline", "onmessage", "onlanguagechange", "onhashchange", "onbeforeunload", "onwaiting", "onvolumechange", "ontoggle", "ontimeupdate", "onsuspend", "onsubmit", "onstalled", "onshow", "onselect", "onseeking", "onseeked", "onscroll", "onresize", "onreset", "onratechange", "onprogress", "onplaying", "onplay", "onpause", "onmousewheel", "onmouseup", "onmouseover", "onmouseout", "onmousemove", "onmouseleave", "onmouseenter", "onmousedown", "onloadstart", "onloadedmetadata", "onloadeddata", "onload", "onkeyup", "onkeypress", "onkeydown", "oninvalid", "oninput", "onfocus", "onerror", "onended", "onemptied", "ondurationchange", "ondrop", "ondragstart", "ondragover", "ondragleave", "ondragenter", "ondragend", "ondrag", "ondblclick", "oncuechange", "oncontextmenu", "onclose", "onclick", "onchange", "oncanplaythrough", "oncanplay", "oncancel", "onblur", "onabort", "onwheel", "onwebkittransitionend", "onwebkitanimationstart", "onwebkitanimationiteration", "onwebkitanimationend", "ontransitionend", "onsearch"]

没错,这些都是JavaScript事件!但也不仅仅是这些。

DOM1级事件处理

为什么不是DOM0级事件,以为DOM0级规范压根就没有形成。DOM1级事件处理是当今所有浏览器都支持的事件处理,不存在任何兼容性问题,。DOM0事件处理的规则:每个DOM元素都有自己的事件处理属性,该属性可以赋值一个函数,例如:

var btnDOM = document.getElementById("btn");
btnDOM.onclick = function(){
    alert("you click me!");            
}

DOM0级事件处理的事件属性都是采用“on+事件名称”的方式定义,整个属性都是小写字母。DOM元素在JavaScript代码是作为对象处理的,例如:

btnDOM.onclick = null;

那么按钮的点击事件被取消了。

DOM1级事件可以被覆盖,例如:

btnDOM.onclick = function(){
    alert(" you click me!");            
}
btnDOM.onclick = function(){
    alert("also click me!");            
}

后面一个函数会将第一个函数覆盖。

DOM2级事件处理(IE9及其以上支持)

首先说说事件流。事件流描述的是从页面中接收事件的顺序。早期的IE事件流叫做事件冒泡,Netscape团队提出的是事件捕获。
如下图:

event-old

而现在常用的DOM2级事件流(也称标准事件模型)是包括了三个阶段:事件捕获阶段,处于目标阶段和事件冒泡阶段。
如下图:

event-standard

DOM2事件处理里添加事件使用的是addEventListener,它接收三个参数,第三个参数默认为false,表示在冒泡阶段调用事件处理程序。如果设为true,则表示在事件捕获阶段处理程序。

var btnDOM = document.getElementById("btn"); 
btnDOM.addEventListener("click",function(){ 
    alert("Click Me!");
},false);
var ftn = function(){ 
    alert("Click Me,too!");
};
btnDOM.addEventListener("click",ftn,false);

删除事件使用removeEventListener,其中参数要和定义事件的参数一致,第三个参数不传,默认是删除冒泡事件,因为第三个参数不传默认都是false,例如下面的代码是不能成功删除事件的:

btnDOM.addEventListener("click",ftn,true);
btnDOM.removeEventListener("click",ftn);

事件冒泡有时候并不是我们所想要的。所以我们需要来阻止事件冒泡,标准方法是:

event.stopPropagation();

IE 可能会使用到下面这个方法:

event.cancelBubble = true;

事件对象event里面存在target和currentTarget。我们知道事件其实是观察者模式。target其实是事件的发布者(event dispatcher),currentTarget是事件的处理者(event processor)。

说明:

  1. target发生在事件流的目标阶段,而currentTarget发生在事件流的整个阶段(捕获、目标和冒泡阶段)
  2. 只有当事件流处于目标阶段的时候二者才相同
  3. 而当事件流处于捕获和冒泡阶段时,target指向被点击的对象,而currentTarget指向当前事件活动的对象。

知道了这个原理,我们便可以理解事件委托(也称事件代理)的实现原理了。

DOM3及DOM4事件处理

这是未来的事情了。

原文地址:https://www.cnblogs.com/myqianlan/p/4196005.html