事件:文档或浏览器窗口中发生的一些特定的交互瞬间。
事件流:描述从页面中接收事件的顺序。
问题:如果在一个web页面上用鼠标点击一个元素a的某一子元素b时,应该先执行子元素b注册的事件处理程序还是先执行元素a注册的事件处理程序呢(假设元素a和它的子元素b都有注册事件处理程序)?
这个问题就涉及到浏览器中的事件传播(event propagation)机制。相信大家都听说过事件冒泡(event bubble)和事件捕获(event capturing)吧。没错,它们就是浏览器中的事件传播机制。如下图所示:
上图大概解释了浏览器中的事件传播机制了:当一个事件发生时,它会先从浏览器顶级对象Window一路向下传递,一直传递到触发这个事件的那个元素,这也就是事件捕获过程。然而,一切并没有结束,事件又从这个元素一路向上传递到Window对象,这也就是事件冒泡过程(但是在IE8以及其之前版本中,事件模型并未定义捕获过程,只有冒泡过程)。
IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
Netscape Communicator 团队提出的另一种事件流叫做事件捕获(event capturing),事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。
补:深入理解事件冒泡和事件捕获
运行结果:
结论:先child,然后parent。事件的触发顺序自内向外,这就是事件冒泡。
运行结果:
结论:先parent,然后child。事件触发顺序变更为自外向内,这就是事件捕获。
事件绑定
要想让 JavaScript 对用户的操作作出响应,首先要对 DOM 元素绑定事件处理函数。(所谓事件处理函数,就是处理用户操作的函数,不同的操作对应不同的名称)
绑定:什么事件发什么了什么事件源要用什么事件处理程序进行绑定。
事件源:发生事件的对象。
怎样进行事件绑定?
首先看下JS中的事件分类:
鼠标事件:onclick, ondbclick, onmouseover,onmousedown, onmouseup,onmouseout...
键盘事件:onkeyup,onkeydown,onkeypress...
表单事件:onsubmit,onblur,onfoucs,onchange..
页面事件:onload,onunload,onreload...
既然有这么多的事件,那么怎么给元素绑定事件?看一下给元素绑定事件应该有几种方法
1.在DOM元素中直接绑定
2.JavaScript代码中直接绑定
3.绑定事件监听函数
一,在DOM元素中直接绑定
这里的DOM元素,可以理解为HTML标签。
JavaScript支持在标签中直接绑定事件,语法为:onXXX="JavaScript Code"
其中:onXXX 为事件名称。例如,鼠标单击事件 onclick ,鼠标双击事件 ondouble,鼠标移入事件 onmouseover,鼠标移出事件 onmouseout 等。
JavaScript Code 为处理事件的JavaScript代码,一般是函数。
举个栗子,单击一个按钮,弹出警告框的代码有如下两种写法:
1).原生函数
2). 自定义函数
二、JavaScript代码中直接绑定
在JavaScript代码中(即<script>标签内)绑定事件可以使JavaScript代码与HTML标签分离,文档结构清晰,便于管理和开发。
在JavaScript代码中绑定事件的语法为:
elementObject.onXXX=function(){
// 事件处理代码
}
其中:elementObject 为DOM对象,即DOM元素。
onXXX 为事件名称。
举个栗子,为 id="demo" 的按钮绑定一个事件,显示它的 type 属性:
三,绑定事件监听函数
绑定事件的另一种方法是用 addEventListener() 或 attachEvent() 来绑定事件监听函数。
addEventListener()函数语法:
elementObject.addEventListener(eventName,handle,useCapture);
其中:elementObject为DOM对象(即DOM元素)
eventName为事件名称。注意,这里的事件名称没有“ on ”,如鼠标单击事件 click ,鼠标双击事件 doubleclick ,鼠标移入事件 mouseover,鼠标移出事件 mouseout 等。
handle为函数名,即用来处理事件的函数。
useCapture为Boolean类型,是否使用捕获,一般用false 。
attachEvent()函数语法:
elementObject.attachEvent(eventName,handle);
其中:elementObject为DOM对象(即DOM元素)。
eventName为事件名称。注意这里的事件名称有“ on ”,如鼠标单击事件 onclick ,鼠标双击事件 ondoubleclick ,鼠标移入事件 onmouseover 等。
handle为函数名,即用来处理事件的函数。
addEventListener()是标准的绑定事件监听函数的方法,是W3C所支持的,Chrome、FireFox、Opera、Safari、IE9.0及其以上版本都支持该函数;但是,IE8.0及其以下版本不支持该方法,它使用attachEvent()来绑定事件监听函数。所以,这种绑定事件的方法必须要处理浏览器兼容问题。
从网上找到了一个兼容的办法,相比较if。。else语句,这个方法用的是try..catch错误处理语句,可以避免浏览器出现错误提示:
例如,为一个 id="demo" 的按钮绑定事件,鼠标单击时弹出警告框:
事件处理程序(event handler)(或事件侦听器(event listener)):
事件源:发生事件的对象。
响应某个事件的函数。文档元素的事件处理程序属性,其名字由“on”后面跟着事件名组成,例如:onclick、onmouseover。
几种事件处理程序的方法:
1).HTML事件处理程序(不常用)
2).DOM0 级事件处理程序(用的比较多的一个方式):先将元素取出来,再对元素属性进行赋值进行事件处理
通过 JavaScript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。
要使用 JavaScript 指定事件处理程序,首先必须取得一个要操作的对象的引用。
每个元素(包括 window 和 document)都有自己的事件处理程序属性,这些属性通常全部小写,例如 onclick。将这种属性的值设置为一个函数,就可以指定事件处理程序,
3).DOM2 级事件处理程序:.addEventListener()方法 /.removeEventListener()方法
“DOM2 级事件” 定义了两个方法,用于处理指定和删除事件处理程序的操作: addEventListener()和 removeEventListener()。所有 DOM 节点中都包含这两个方法,并且它们都接受 3 个参数:要注册处理程序的事件类型,其值是字符串,但并不包括前缀“on”;第二个参数是指当指定类型的事件发生时应该调用的函数;第三个参数是布尔值,其可以忽略(某些旧的浏览器上不能忽略这个参数),默认值为false。最后这个布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。
通过EventListener()添加的事件处理程序只能使用 removeEventListener()来移除;移除时传入的参数与添加处理程序时使用的参数相同。
4).IE事件处理程序:
IE 实现了与 DOM 中类似的两个方法: attachEvent()和 detachEvent()。因为IE8以及其之前版本浏览器也不支持事件捕获,所以attachEvent()并不能注册捕获过程中的事件处理函数,因此attachEvent()和detachEvent()要求只有两个参数:事件类型和事件处理函数。而且,它们的第一个参数使用了带“on”前缀的事件处理程序属性名。
通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段。
使用 attachEvent()添加的事件可以通过 detachEvent()来移除,条件是必须提供相同的参数。
5).跨浏览器的事件处理程序
事件对象
事件对象封装了所有与事件有关的信息。
IE的获取是window.event 其他浏览器直接获得即可:event 所以在使用的时候这样定义:event=event || window.event
在触发 DOM 上的某个事件时,会产生一个事件对象 event,这个对象中包含着所有与事件有关的信息。
注意:只有在事件处理程序执行期间, event 对象才会存在;一旦事件处理程序执行完成, event 对象就会被销毁。
1.DOM中的事件对象
1)type属性:用于获取事件类型 (event.type)
2)target属性:用于获取事件目标 (event.target / event.target.nodeName)
3)stopPropagation():用于阻止事件冒泡
4)preventDefault():阻止事件的默认行为
2.IE中的的事件对象
1)type属性:用于获取事件类型 (event.type)
2)srcElement属性:用于获取事件的目标
3)cancelBubble属性:用于阻止事件冒泡(设置为true表示阻止冒泡 设置false表示不阻止冒泡)
4)returnValue属性:用于阻止事件的默认行为(设置为false表示阻止事件默认行为)
3.跨浏览器的事件对象
1). getEvent(),它返回对 event对象的引用
2). getTarget(),它返回事件的目标。在这个方法内部,会检测 event 对象的 target属性,如果存在则返回该属性的值;否则,返回 srcElement 属性的值。
3). preventDefault(),用于取消事件的默认行为。在传入 event 对象后,这个方法会检查是否存在 preventDefault()方法,如果存在则调用该方法。如果 preventDefault()方法不存在,则将 returnValue 设置为 false。
4). stopPropagation(),其实现方式类似。
事件类型(event type):是一个用来说明发生什么类型事件的字符串
1.1). load事件:当页面加载完后(包括所有图像,所有javascript文件,css文件等外部资源),就会触发window上面的load事件
2).焦点事件:当元素获得或失去焦点时触发
3).鼠标事件:当用户通过鼠标在页面操作时触发
4).滚轮事件(mousewheel 事件)
5).键盘事件
6).文本事件
2.理解坐标位置
1).客户区坐标位置:标事件都是在浏览器视口中的特定位置上发生的。这个位置信息保存在事件对象的 clientX 和clientY 属性中。所有浏览器都支持这两个属性,它们的值表示事件发生时鼠标指针在视口中的水平和垂直坐标。
2).页面坐标位置:通过客户区坐标能够知道鼠标是在视口中什么位置发生的,而页面坐标通过事件对象的 pageX 和pageY 属性,能告诉你事件是在页面中的什么位置发生的。
在页面没有滚动的情况下, pageX 和 pageY 的值与 clientX 和 clientY 的值相等。
3).屏幕坐标位置:而通过 screenX 和 screenY 属性就可以确定鼠标事件发生时鼠标指针相对于整个屏幕的坐标信息。
五.事件委托
解决方法:把事件绑定给祖先元素。
动态的元素(自定义添加的元素),不能用普通的事件绑定元素。
六,事件中常用的通用代码整理: