事件与事件流
事件是与浏览器或文档交互的瞬间,如点击按钮,填写表格等,它是JS与HTML之间交互的桥梁。DOM是树形结构,若同时给父子结点绑定了相同的事件,那么他们的执行顺序是什么样子的呢?这就涉及到了事件流的概念。首先解释两个概念:
事件冒泡
IE的事件流叫事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的节点)接收,然后逐级向上传播到较为不具体的节点。
事件捕获
Netscape团队提出的另一种事件流叫事件捕获,事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
一个DOM事件分为三个阶段:捕获阶段、触发阶段、冒泡阶段。

事件捕获阶段为事件的触发奠定了基础,当DOM事件发生的时候,首先由最不具体的window结点向下捕获那个具象元素(触发事件的元素),事件捕获之后就开始执行绑定在上面的函数;当函数执行完毕,触发事件冒泡进入冒泡阶段,一直从触发的元素逐级想上传递,直至window元素。
事件模型
DOM0级事件
这样的事件模型中,事件是没有事件流的概念的,事件的绑定比较简单:
直接在HTML中绑定事件处理函数
<button onclick="fun()">
通过在js中获取元素来绑定事件
var btn = document.getElementById("btn");
btn.onclick = fun;
移除事件
btn.onclick = null;
DOM2级事件
DOM2级事件现代浏览器都支持,事件流的概念也是支持的。
绑定方式
addEventListener(eventType, handler, useCapture)
移除方式
removeEventListener(eventType, handler, useCapture)
最后一个参数是一个boolean类型的参数,表示是否捕获过程,不填为false。
IE事件
IE事件,取消了事件流中的事件捕获过程。
绑定方式
attachEvent(eventType, handler)
移除方式
detachEvent(eventType, handler)
事件封装
EventUtil={
addListener:function(target,type,handler){
if(target.addEventListener){
target.addEventListener(type,handler);
}else if(target.attachEvent){
target.attach("on"+type,function(){
handler.call(target); //让handler中的this指向目标元素
});
}else{
target["on"+type]=handler;
}
},
removeListener:function(target,type,handler){
if(target.removeEventListener){
target.removeEventListener(type,handler);
}else if(target.detachEvent){
target.detachEvent("on"+type,handler);
}else{
target["on"+type]=null;
}
},
getEvent:function(e){ //获取事件对象
var evt=window.event||e;
return evt;
},
getTarget:function(e){ //获得目标对象
var evt=EventUtil.getEvent(e);
var target;
if(evt.target){ target=evt.target;}
else {target=evt.srcElement;}
return target;
},
stopPropagation:function(e){ //停止冒泡
var evt=EventUtil.getEvent(e);
if(evt.stopPropagation) {evt.stopPropagation();}
else {evt.cancelBubble=true;}
},
preventDefault:function(e){ //阻值默认行为的发生
var evt=EventUtil.getEvent(e);
if(evt.preventDefault){ evt.preventDefault(); }
else {e.returnValue=false;}
}
}
事件代理
事件在冒泡过程中会上传到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理(Event delegation)。
<div id="box">
<input type="button" value="按钮" id="btn">
<input type="button" value="按钮2" id="btn2">
<input type="button" value="按钮3" id="btn3">
</div>
直接通过父节点一次性为所有子结点注册监听函数:
var box = document.getElementById('box');
box.addEventListener('click', function(event) {
if (event.target.tagName.toLowerCase() === 'input') {
// some code
}
});
Mouse 事件
常见的鼠标事件主要是以下几种:
- mousedown:鼠标的键钮被按下。
- mouseup:鼠标的键钮被释放弹起。
- click:单击鼠标的键钮。
- dbclick:鼠标的键钮被按下。
- contextmenu :弹出右键菜单。
- mouseover:鼠标移到目标的上方。
- mouseout:鼠标移出目标的上方。
- mousemove:鼠标目标的上方移动。
mousedown事件与mouseup事件可以说click事件在时间上的细分,顺序是mousedown => mouseup => click。因此一个点击事件,通常会激发几个鼠标事件。
在 HTML5 中鼠标有了新的事件,如下表格:
| 属性 | 描述 |
|---|---|
| ondrag | 元素被拖动时运行的脚本。 |
| ondragend | 在拖动操作末端运行的脚本 |
| ondragenter | 当元素元素已被拖动到有效拖放区域时运行的脚本。 |
| ondragleave | 当元素离开有效拖放目标时运行的脚本。 |
| ondragover | 当元素在有效拖放目标上正在被拖动时运行的脚本 |
| ondragstart | 在拖动操作开端运行的脚本 |
| ondrop | 当被拖元素正在被拖放时运行的脚本 |
| onmousewheel | 当鼠标滚轮正在被滚动时运行的脚本。 |
| onscroll | 当元素滚动条被滚动时运行的脚本。 |
对上述新增事件的详解参考www.w3school.com.cn/tags/html_r…
Keyboard 事件
键盘事件相对较简单,主要在于根据键盘上每个按键对应的ascII码,来执行相应的脚本。
| 属性 | 描述 |
|---|---|
| onkeydown | 在用户按下按键时触发。 |
| onkeypress | 在用户敲击按钮时触发。 |
| onkeyup | 当用户释放按键时触发。 |
Form 事件
下面是Form事件的常见类型:
| 属性 | 描述 |
|---|---|
| onblur | 元素失去焦点时运行的脚本。 |
| onchange | 在元素值被改变时运行的脚本。 |
| onfocus | 当元素获得焦点时运行的脚本。 |
| onreset | 当表单中的重置按钮被点击时触发。HTML5 中不支持。 |
| onselect | 在元素中文本被选中后触发。 |
| onsubmit | 在提交表单时触发。 |
如下为Form事件新增的事件类型:
| 属性 | 描述 |
|---|---|
| oncontextmenu | 当上下文菜单被触发时运行的脚本。 |
| onformchange | 在表单改变时运行的脚本。 |
| onforminput | 当表单获得用户输入时运行的脚本。 |
| oninput | 当元素获得用户输入时运行的脚本。 |
| oninvalid | 当元素无效时运行的脚本。 |
主要参考的技术网站如下:
li-xinyang.gitbooks.io/frontend-no…
segmentfault.com/a/119000000…
segmentfault.com/a/119000000…
leohxj.gitbooks.io/front-end-d…
www.cnblogs.com/rubylouvre/…