事件分为两部分
事件分为两部分:1.行为本身和事件绑定
1.行为本身:浏览器天生就赋予其的行为(mouseover mouseenter mouseout mouseleave mousemove mousedown mousewheel mouseup scroll resize click load unload focus blur keydown keyup),即使没有给上述方法绑定事件,事件也是存在的,只是什么事都没做。
2.事件绑定: 给元素的某一个行为绑定方法。
绑定事件的方法:
a)DOM0级事件绑定
DOM.onclick = function(){ click行为定义在当前元素的私有属性上}
DOM0级事件绑定:同一个元素绑定同一个事件名以后定义的为准
b)DOM2级事件绑定
DOM.addEventListener('click',function(){ addEventListener属性定义在EventTarget这个类的原型上 })
DOM2级事件绑定:同一个元素多次绑定同一个事件,不同的方法,都会执行,如果事件名相同,方法名也相同并且执行阶段也相同,那么只会执行一个。
同时,DOM2还有除了DOM0中的行为外,还有一下行为类型:
DOMContentLoaded:html结构(不含图片..)加载触发事件。
在用DOM2级事件绑定的时候,里面的fn要使用实名函数,方便不用的时候解除。
事件移除: removeEventListener(type,fnname,boolean) 要和绑定的时候保持一致;
兼容性: IE6-8 绑定事件:attachEvent('onclick',fn) 只能在冒泡阶段发生
解除事件:detachEvent('onclick',fn) 只能在冒泡阶段发生
事件对象及兼容处理
在元素的事件方法执行的时候,浏览器默认的给执行的方法传递了一个参数:MouseEvent
MouseEvent:一个对象数据类型值,里面包含的属性名和属性值都是用来记录鼠标的相关信息的。
MouseEvent记录的是页面中唯一一个鼠标每一次触发的相关信息,和到底是在哪个元素上触发的没有关系。
兼容性:
MouseEvent:支持ie9+(标准浏览器);
window.event: 支持ie8及以下和标准浏览器(火狐除外)。
兼容写法: var e = e || window.event
e.type: 存储的是当前鼠标触发的行为类型;
e.clientX: 鼠标距离浏览器可视区域的X坐标;
e.keyCode : 键盘码 这时的 e 是 KeyboardEvent;
e.pageX:鼠标距离页面文档的X坐标(支持标准浏览器,IE6-8没有可通过clientY+滚动卷去的高度获取)。
e.pageX = e.pageX || (e.clientX + (document.documentElement.scrollLeft|| document.body.scrollLeft))
事件源(有兼容性):
e.target:当前鼠标触发的是那个元素,支持标准浏览器;
e.srcElement: IE6-8支持
兼容性: e.target = e.target || e.srcElement
阻止浏览器的默认行为:
e.preventDefault() 支持标准浏览器;
e.returnValue = false 支持IE6-8;
兼容写法:1.e.preventDefault?e.preventDefault():e.returnValue=false
2.return false;
阻止事件冒泡:
e.stopPropagation() 支持标准浏览器
e.cancelBubble = false 支持IE6-8;
兼容写法:e.stopPropagation?e.stopPropagation():e.cancelBubble=true
事件的传播机制
事件的阶段:捕获阶段、目标阶段、冒泡阶段
捕获阶段:从外向内一次查找元素。
目标阶段:当前事件源本身的操作(方法执行)。
冒泡阶段:从内到外依次触发相关的行为(最常用的阶段)
使用DOM0级事件绑定给元素的某一个行为绑定的方法,都是在行为触发后的冒泡阶段把方法执行的。
在IE中传播到html,在chrome下传播到document;
在捕获阶段完成方法执行时,需要使用DOM2级事件绑定,写法如下:
DOM.addEventListener('click',function(){},boolean)
boolean:true 在捕获阶段发生function 在捕获阶段发生的fn先执行;
false 在冒泡阶段发生function
事件委托
利用事件的冒泡传播机制,如果一个容器中很多的元素都需要给点击事件绑定方法(之前是一个个的循环绑定的),我们现在不需要一个个的绑定,只需要给最外层的这个容器绑定一次即可,这样的话,不管点击里面的哪一个元素,最终都会传播到最外层的容器上,我们只需要获取到事件源(点击的那一个),根据不同的事件源做不同的处理即可。 优点:使用事件委托来处理,会比一个个的绑定的性能调高至少一倍
事件池
事件池用来存储当前元素行为绑定方法的(浏览器自带的机制)。
事件池的机制:
1.只能给某个元素的同一个行为绑定多个不同的方法,如果方法相同了只能留一个;
2.事件会按照绑定的顺序从上到下执行;
3.执行的方法中的this是当前被绑定事件的元素本身。
IE678和标准浏览器的事件池机制对比:
1.顺序问题: 执行的时候顺序是混乱的,标准浏览器按照顺序依次执行
2.重复问题:IE678可以给同一个元素的同一个行为绑定多个相同的方法
3.this问题: IE678中当方法执行的时候,方法中的this不是当前被绑定事件的元素而是window