-
Notifications
You must be signed in to change notification settings - Fork 0
Description
事件概述
事件是javascript和HTML交互基础, 任何文档或者浏览器窗口发生的交互, 都要通过绑定事件进行交互;
事件响应是异步处理的
事件响应是异步处理的, 当某个事件触发时,不一定马上会得到响应,而是异步处理的,响应的时间是不一定的。
事件的分类
DOM0/原始 事件模型
- 所有的浏览器都支持
- 绑定速度最快,直接写在元素上
- 只能绑定一个handler
- 没有冒泡还是捕获之说
- handler中获取event对象各浏览器差异
- 删除 element.on+event = null;
<!-- DOM0 绑定的方法 -->
<a id="foo" href="javascript;" onclick="alert('did stuff inline');">Click me</a>
<script type="text/javascript">
// HTML 中的 onclick="" 属性 和 element.onclick 等同
document.getElementById('foo').onclick = fucntion(){
alert('did stuff inline');
}
</script>
DOM2/标准 事件模型
IE事件模型(>=IE9,同时也支持标准事件模型)
标准事件模型与IE的事件模型的区别
| 选项 | 标准事件模型 | IE事件模型(IE9之前) |
|---|---|---|
| 支持冒泡和捕获 | 都支持 | 只支持冒泡 |
| 绑定方法 | addEventListener | attachEvent(ie5及+) |
| 解绑方法 | removeEventListener | detachEvent(ie5及+) |
| 事件的名称参数 | 事件名字,例如click | on+事件名字,例如onclick |
| 事件hanlde中对事件对象的获取 | 事件处理函数的第一个参数或window.event(FF不支持) | 通过window.event或事件处理函数的第一个参数 |
| 事件hanlde中的this | 事件绑定的对象 | window |
| 阻止冒泡的方法 | event.stopPropagation(); | event.cancelBubble = true; |
| 阻止默认行为的方法 | event.preventDefault(); | event.returnValue = false; |
| 事件target | event.target | event.srcElement |
| 事件relatedTarget | event.relatedTarget | event.fromElement/event.toElement |
| 冒泡过程中currentTarget | event.currentTarget | 无 |
| 单个元素添加多个事件处理程序,执行的顺序 | 执行顺序按照它们添加的顺序执行 | 执行顺序按照添加的顺序相反的顺序执行 |
-
支持冒泡和捕获
- 支持冒泡和捕获
- 只支持冒泡
-
绑定方法
- addEventListener
- attacthEvent
var eventUtil = { on : function(el, type, handler) { if(el.addEventListener) { el.addEventListener(type, handler, false); }else if( el.attachEvent ) { el.attachEvent("on"+type, handler); }else{ el["on"+type] = handler; } }, off : function(el, type, handler) { if( el.removeEventListener ) { el.removeEventListener(type, handler, false) }else if( el.detachEvent ) { el.detachEvent(type, handler); }else{ el["on"+type] = null; } } };
-
解绑方法
- removeEventListener
- detachEvent
-
事件的名称参数
- 事件名字,例如click
- on+事件名字,例如onclick
-
事件hanlde中对事件对象的获取
- 支持标准事件模型的浏览器,不管用addEventListener还是ele.onclick方式绑定事件,通过事件处理的handle函数第一个参数就可以获取event对象;
- 而IE不支持标准事件模型的浏览器(<IE9),ele.onclick方式绑定事件时,只能用window.event来获取
function handle(event){ var event = event || window.event; //... } ele.attachEvent && ele.attachEvent("onclick", handler); ele.addEventListener && ele.addEventListener("click", handler, false); ele.onclick = handler;
-
事件hanlde中的this
- addEventListener绑定事件的handle中的this指向被绑定的元素ele
- attacthEvent绑定事件的handle中的this指向window,而不是被绑定的元素ele
-
阻止冒泡的方法
- event.stopPropagation();
- event.cancelBubble = true;
function handle(event){ var event = event || window.event; if(event.stopPropagation){ event.stopPropagation(); }else { event.cancelBubble= true; } //... }
-
阻止默认行为的方法
- event.preventDefault();
- event.returnValue = false;
function handle(event){ var event = event || window.event; if(event.preventDefault){ event.preventDefault(); }else{ event.returnValue = false; } //... }
-
事件target
- event.target
- event.srcElement
function handle(event){ var event = event || window.event; var target = event.target || event.srcElement; //... }
-
事件的relatedTarget
- relatedTarget
- fromElement/toElement
function handle(event){ var event = event || window.event; var relatedTarget = event.relatedTarget || event.fromElement/*toElement*/; //... }
事件对象的其他参数
冒泡和捕获
冒泡带来的便利和不便
- 通过冒泡机制来实现事件代理
- 冒泡对某些事件的处理带来困扰例如mouseover/mouseout
事件代理
因为事件有冒泡机制,所有子节点的事件都会顺着父级节点跑回去,所以我们可以通过监听父级节点来实现监听子节点的功能,这就是事件代理。
使用事件代理主要有两个优势:
- 减少事件绑定,提升性能。之前你需要绑定一堆子节点,而现在你只需要绑定一个父节点即可。减少了绑定事件监听函数的数量。
- 动态变化的 DOM 结构,仍然可以监听。当一个 DOM 动态创建之后,不会带有任何事件监听,除非你重新执行事件监听函数,而使用事件监听无须担忧这个问题。
不能冒泡的事件
-
focus/blur事件不冒泡,但focusin and focusout Fire at the same time as focus and blur会冒泡。
from -
mouseenter/mouseleave(only ie/opera 支持)不冒泡,在mouseover/mouseout时触发会冒泡
-
submit/reset事件
功能:监听表单的提交/重置;在IE6到IE8下只会冒泡到当前提交表单所在的form标签中,也就说document下直接代理监听多个表单提交会有兼容性问题。
-
change事件
功能:监听元素value值的改变,input和select 在blur才触发;change事件在IE6到IE8,chrome,safari下都不会冒泡,也不能像focus和blur一样可以用focusin和focusout替代,在IE下也不能通过设置captrue实现对事件的捕获,其他高级浏览器下可以。
-
select事件
功能:监听文本域中文字的选中。select事件在IE6到IE8,chrome,safari下都不会冒泡,但是比change好的一点是,在IE下可以使用selectstart替代,而在高级浏览器中可以直接设置captrue为捕获即可。
键盘事件
键盘事件的触发流程
一个典型的按键输入,依次触发的事件依次是
- keydown
- keypress
- keypress事件触发后,input元素更新value属性
- keyup
如果一个按键被按下并重复按下,则可能在keydown和keyup事件之间触发多个keypress事件。
键盘事件的兼容性
| 选项 | 其他浏览器 | IE |
|---|---|---|
| 不能打印的功能按键(退格,回车,escape)和箭头方向键,翻页键,F1-F12 | 有时候会触发keypress事件 | IE只有当按键有一个ASCII码的时候,才会触发keypress |
| 获取按键码的事件属性 | keyeCode/charCode | keyCode |
| keydown/keyup | keyeCode为虚拟按键码/charCode为0 | keyCode为虚拟按键码 |
| keypress | keyeCode为虚拟按键码/charCode为虚拟按键码,FF为0 | keyCode为字符的ASCII值 |
| 输入中文时 | 不触发keypress,大部分浏览器触发keydown,keycode为229 | 不触发keypress,触发keydown,keycode为229 |
常见案例
- 过滤输入框的字符只能输入特定的字符
- keyup + change(粘贴)
- 搜索框的suggest
- keyup + paste(粘贴) ?
键盘事件的兼容性列表
鼠标事件
鼠标事件的触发流程
一个典型的鼠标拖动操作,依次触发的事件依次是
- mouseover
- mousedown
- mousemove
- mouseup
- click
- mouseout
如果中间鼠标移动,将会触发多个mousemove事件。
鼠标事件的问题
-
mousedown/mouseup不一定都会触发
当按下鼠标进入目标或按下鼠标移出目标区域 -
mouseover和mouseout的冒泡问题
适当的用mouseenter和mouseleave替代mouseover和mouseout
jQuery/zepto的事件绑定
//绑定
$(ele).on( events [, selector ] [, data ], handler );
//触发事件
$(elementA).trigger( events );