最近一个多月真是忙到飞起啊,活脱脱把美少女变成了国宝,终于告一段落,留给个人,依然是无处安放的,魅力(黑眼圈)啊~
话很少说,先啃为敬 ^_^javascript
JavaScript与HTML之间的交互式经过事件实现的。
事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。html
IE的事件流叫作事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,而后诸暨向上传播到较为不具体的节点(文档)。
好比一个<body>标签中只包含一个<div>元素的页面,若是你点击了页面中的<div>,那么这个click事件会按照以下顺序传播:
(1) <div>
(2) <body>
(3) <html>
(4) document
也就是说,click事件首先在<div>元素上发生,而这个元素就是咱们点击的元素。
而后,click事件沿DOM树向上传播,在每一级节点上都会发生,直至传播到document对象。
下图完美的展现了时间冒泡的过程。java
事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
事件捕获的用意在于在事件到达预约目标以前捕获它。以上面冒泡的例子,单击<div>元素就会如下列顺序触发click事件
(1) document
(2) <html>
(3) <body>
(4) <div>
在事件捕获过程当中,document对象首先接收到click事件,而后事件沿DOM树依次向上,一直传播到事件的实际目的,即<div>元素。以下图:ios
"DOM2级事件"规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
首先发生的是事件捕获,为截获事件提供了机会。而后是实际的目标接收到事件。最后一个阶段是冒泡阶段,能够在这个阶段对事件作出响应。浏览器
事件就是用户或浏览器自身执行的某种动做。诸如click、load和mouseover,都是事件的名字。而响应某个事件的函数就叫作事件处理程序(或事件监听器)。
事件处理程序的名字以"on"开头,所以click事件的事件处理程序就是onclick,load事件的事件处理程序就是onload。为事件指定处理程序的方式有好几种。框架
事件处理程序中的代码在执行时,有权访问全局做用域中的任何代码。
这样指定事件处理程序具备一些独到之处。首先,这样会建立一个封装着元素属性值的函数,这个函数中有一个局部变量event,也就是事件对象<input type="button" value="Click Me" onclick="alert(event.type)"> //输出"click"
经过event变量,能够直接访问事件对象,你不用本身定义它,也不用从函数的参数列表中读取。在这个函数内部,this值等于事件的目标元素,例如:<input type="button" value="Click Me" onclick="alert(event.type)"> //输出 "Click Me"
函数
每一个元素(包括window和document)都有本身的时间处理程序属性,这些属性一般所有小写,例如onclick,将这种属性的值设置为一个函数,就能够指定事件处理程序。性能
var btn = document.getElementById("myBtn"); btn.onclick = function(){ alert(this.id); //"myBtn" } btn.onclick = null; //删除事件处理程序
"DOM2级事件"定义了两个方法,用于处理指定和删除事件处理程序的操做:addEventListener()和removeEventListener()。
全部DOM节点中都包含这两个方法,而且它们都接受3个参数:要处理的事件名、做为事件处理程序的函数和一个布尔值。
最后这个布尔值参数若是是true,表示在捕获阶段调用事件处理程序;若是是false,表示在冒泡阶段调用事件处理程序。this
var btn = document.getElmentById("myBtn"); btn.addEventListener("click",function(){ alert(this.id); },false); //该事件会在冒泡阶段被触发 btn.addEventListener("click",function(){ alert("Hello world!"); },false);
使用DOM2级方法添加事件处理程序的主要好处是能够添加多个事件处理程序。
上面的例子为按钮添加了两个事件处理程序,这两个事件处理程序会按照添加它们的顺序触发,所以首先会显示元素的ID,其次会显示"Hello world!"消息。
经过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。这也意味着经过addEventListener()添加的匿名函数将没法移除。就像上面的例子同样。spa
IE实现了与DOM中相似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的两个参数:事件处理程序名字与事件处理程序函数。
要使用attachEvent()为按钮添加一个事件处理程序,可使用如下代码。
var btn = document.getElementById("myBtn"); btn.attachEvent("onclick",function(){ alert("Clicked"); });
注意,attachEvent()的第一个参数是"onclick",而非DOM的addEventListener()方法中的"click"。
在IE中使用attachEvent()与使用DOM0级方法的主要区别在于事件处理程序的做用域。在使用DOM0级方法的状况下,事件处理程序会在其所属元素的做用域内运行;在使用attachEvent()方法的状况下,事件处理程序会在全局做用域中运行,因袭this等于window。
var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function(){
alert(this === window); //true
});
在编写跨浏览器的代码时,牢记这一区别很是重要。
与addEventListener()相似,attachEvent()方法也能够用来为一个元素添加多个事件处理程序。
与DOM方法不一样的是,这些事件处理程序不是以添加它们的顺序执行,而是以相反的顺序被触发。
使用attachEvent()添加的事件能够经过detachEvent()来移除,条件是必须提供相同的参数。与DOM方法同样,这也意味着添加的匿名函数将不能被移除。
兼容DOM的浏览器会将一个event对象传入到事件处理程序中。不管指定事件处理程序时使用什么方法(DOM0级或DOM2级),都会传入event对象。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.type); //"click" }; btn.addEventListener("click", function(event) { alert(event.type); //"click" }, false);
event对象包含与建立它的特定事件有关的属性和方法。触发的事件类型不同,可用的属性和方法也不同。全部的事件都会有下表列出的成员。
在事件处理程序内部,对象this始终等于currentTarget的值,而target则只包含事件的实际目标。
若是直接将事件处理程序制定给了目标元素,则this、currentTarget和target包含相同的值。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.currentTarget === this); //true alert(event.target === this); //true }
要阻止特定事件的默认行为,可使用preventDefault()方法。
例如,连接的默认行为就是在被单击时会导航到其href特性指定的URL。若是你想阻止连接导航这一默认行为,那么经过连接的onclick事件处理程序能够取消它。
var link = document.getElementById("myLink"); link.onclick = function(event) { event.preventDefault(); }
只有cancelable属性设置为true的事件,才可使用preventDefault()来取消其默认行为。
另外,stopPropagation()方法用于当即中止事件在DOM层次中的传播,即取消进一步的事件捕获或冒泡。
例如,直接添加到一个按钮的时间处理程序能够调用stopPropagation(),从而避免触发注册在document.body上面的事件处理程序。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert("Clicked"); event.stopPropagation(); }; document.body.onclick = function(event) { alert("body clicked"); }
对于上面例子,若是不调用stopPropagation(),就会在单击按钮时出现两个警告框,但是因为click事件根本不会传播到document.body,所以就不会触发注册在这个元素上的onclick事件处理程序。
事件对象的eventPhase属性,能够用来肯定事件当前正位于事件流的哪一个阶段。
若是是在捕获阶段调用的事件处理,那么eventPhase等于1;
若是事件处理程序处于目标对象上,则eventPhase等于2;
若是是在冒泡阶段调用的事件处理程序,eventPhase等于3.
这里要注意的是,尽管“处于目标”发生在冒泡阶段,但eventPhase仍然一直等于2。
var btn = document.getElementById("myBtn"); btn.onclick = function(event){ alert(event.eventPhase); //2 }; document.body.addEventListener("click", function(event){ alert(event.eventPhase); //1 }, true); document.body.onclick = function(event) { alert(event.eventPhase); //3 };
当单击这个例子中的按钮时,首先执行的事件处理程序是在捕获阶段触发的添加在document.body中的那一个,结果会弹出一个警告框显示表示eventPhase的1。接着,会触发在按钮上注册的事件处理程序,此时的eventPhase值为2。最后一个被触发的事件处理程序,是在冒泡阶段执行的添加到document.body上的那一个,显示eventPhase的值为3。而当eventPhase等于2时,this.target和currentTarget始终都是相等的。
只有在事件处理程序执行期间,event对象才会存在;一旦事件处理程序执行完成,event对象就会被销毁。
Web浏览器中可能发生的事件有不少类型。
UI事件指的是那些不必定与用户操做有关的事件。
焦点事件会在页面得到或失去焦点时触发。利用这些事件并与document.hasFocus()方法及document.activeElement属性配合,能够知晓用户在页面上的行踪。
页面上的全部元素都支持鼠标事件。
除了mouseenter和mouseleave,全部鼠标事件都会冒泡,,也能够被取消,而取消鼠标事件将会影响浏览器的默认行为。
只有在同一个元素上相继触发mousedown和mouseup事件,才会触发click事件;若是mousedown和mouseup中的一个被取消,就不会触发click事件。
相似地,只有触发两次click事件,才会触发一次dblclick事件。
这四个事件触发的顺序始终以下:
(1)mousedown
(2)mouseup
(3)click
(4)mousedown
(5)mouseup
(6)click
(7)dblclick
显然,click和dblclick事件都会依赖于其余先行事件的触发;而mousedown和mouseup则不受其余事件的影响。
1.客户区坐标位置
鼠标事件都是在浏览器视口中的特定位置上发生的。这个位置信息保存在事件对象的clientX和clientY属性中。
它们的值表示事件发生时鼠标指针在视口中的水平和垂直坐标。
2.页面坐标位置
经过客户区坐标可以知道鼠标是在视口中什么位置发生的,而页面坐标经过事件对象的pageX和pageY属性,能告诉你事件是在页面中的什么位置发生的。换句话说,这两个属性表示鼠标光标在页面中的位置,所以坐标是从页面自己而非视口的左边和顶边计算的。
在页面没有滚动的状况下,pageX和pageY的值与clientX和clientY的值相等。
3.屏幕坐标位置
鼠标事件发生时,不只会有相对于浏览器窗口的位置,还有一个相对于整个电脑屏幕的位置。而经过screenX和screenY属性就能够肯定鼠标事件发生时鼠标指针相对于整个屏幕的坐标信息。
4.鼠标按钮
只有在主鼠标按钮被单击时才会触发click事件,所以检测按钮的信息并非必要的。但对于mousedown和mouseup事件来讲,则在其event对象存在一个button属性,表示按下或释放的按钮。
DOM的button属性可能有以下3个值:0表示主鼠标按钮,1表示中间的鼠标按钮(鼠标滚轮按钮),2表示次鼠标按钮。
4.触摸设备
ios和Android设备的实现很是特别,由于这些设备没有鼠标。
有3个键盘事件,简述以下。
touchstart:当手指触摸屏幕时触发;即便已经有一个手指放在了屏幕上也会触发。
touchmove:档收视在屏幕上滑动时连续地触发。在这个事件发生期间,调用preventDefault()能够阻止滚动。
touchend:当手指从屏幕上移开时触发。
touchcancel:当系统中止跟踪触摸时触发。
以上这几个事件都会冒泡,也都会取消。
ios2.0中的Safari还引入了一组手势事件。当两个手指触摸屏幕时就会产生手势,手势一般会改变显示项的大小,或者旋转显示项。
内存和性能——事件委托
对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就能够管理某一类型的全部事件。例如,click事件会一直冒泡到document层次。
若是可行的话,也能够考虑为document对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件。优势以下:
最适合采用事件委托技术的事件包括click、mousedown、mouseup、keydown、keyup和keypress。虽然mouseover和mouseout事件也冒泡,但要适当处理它们并不容易,并且常常须要计算元素的位置。(由于当鼠标从一个元素移到其子节点时,或者当鼠标移出该元素时,都会触发mouseout事件。)
小结
事件是将Javascript与网页联系在一块儿的主要形式。“DOM3级事件”规范和HTML5定义了常见的大多数事件。即便有规范定义了基本事件,但不少浏览器仍然在规范以外实现了本身的专有事件,从而为开发人员提供更多掌握用户交互的手段。
事件是Javascript中最重要的主题之一,深刻理解事件的工做机制以及它们对性能的影响相当重要。
好啦,事件就大概记到这里啦~