我们可以简单的把事件理解为浏览器的感知系统。比如说:他可以感觉到用户是否点击(click)了页面、鼠标是否进入了页面的某个元素上面(mouseover或mouseenter)、鼠标是否离开了网页(mouseout或mouseleave)、浏览器是都加载完了页面上的资源(window.onload)、文档树是否生成(DOMContentLoaded)、键盘上的某个键是否按下(keydown)、鼠标的滚轮是否滚动了等等。
其实事件的原理并非是浏览器的感觉系统,它的本质是一个行为发生时,对另一个行为的回调。
事件的绑定就是:当这个事件发生的时候,运行一个或者多个方法(function),比如说当鼠标点击页面的时候,就弹出一个“事件”,则写成:
document.onclick = function(){alert("事件“);}
事件的绑定相当于做计划,绑定在事件上的方法执行了就相当于计划的事发生了,所以一般情况下,事件属性的前面都有”on“,如:ele.onclick, ele.onmousedown, ele.onmouseup, 这里的on,其实就相当于:当什么时候,做计划要早于计划的事件发生。
当然我们也可以不给事件绑定处理方法,也就是说当此事件发生的时候,什么也不需要做,事件常有,而事件上绑定的方法不一定有,
我们给页面中的元素的某个事件绑定处理方法的时候。经常还会有一个形式参数e,但是运行的事件,却没有办法传递实参给这个形参e,比如:
function fn (e){
//标准浏览器中:定义一个形参e,但当事件触发的时候,并没有给e赋实际的值,则浏览器会把”事件“的对象赋给这个形参e,这时这个e是个系统级的对象:事件;
IE中的事件对象是个全局的属性window.event,而标准浏览器的事件对象就是形参e;
所以事件对象的兼容性写法为:e = e||window.event;
var x =e.clientX,y=e.clientY;所有浏览器都支持,相当于浏览器中鼠标的坐标;
var x=e.pageX,y = e.pageY;ie8或以下不支持,相当于文档的中鼠标的坐标;
target事件源;事件源的概念:事件最终发生在页面的那个元素上;
事件源和事件的传播是息息相关的
事件的传播包括:冒泡和捕获;事件传播是浏览器在处理事件行为的机制,冒泡阶段或者捕获阶段。 注意:ie 678里,事件传播只有冒泡阶段;
var target = e.target||e.srcElement 后者是处理ie兼容‘;
div1.innerHTML="当前的事件类型:”+e.type+“鼠标的X坐标:“+x+”鼠标的Y坐标:“+Y+”事件发生在哪儿:“+e.target;
}
document.onmousemove=fn;把烦恼直接赋值给document的onmousemove这个属性
var ele = document.getElememtById('div1');
document.onkeydown = function(e){
e=e||wondow.event;//处理事件对象兼容性
//console。log(e.keyCode):keyCode是是当前的这个键值对应的ASCII码
switch(e.keyCode){
case 37://键盘上的左键
ele.style.left = ele.offserLeft-5+"px";
break;
case 38://上
ele.style.top = ele.offfsetTop-5+'px';
break;
}
}
以上这样的事件绑定方法(就是直接把fn赋给document.onmousemove的方式)叫DOM0级事件绑定,它是相当于DOM2级事件绑定来说的
很多的网页元素都会有默认的行为,比如说当你点击一个超链接a0标签的时候,他就会有一个跳转行为;当你在网页上点击鼠标右键的时候会出现一个右键菜单;当你在一个form表单里点击提交按钮时网页会产生一个行为病刷新网页,当你网页上滚动鼠标滚轮的时候,页面的滚动条会滚动等等;这些都叫事件的默认行为,如果想把这些默认行为取消了,相应的js代码如下:
a.onclick = function(){return false}//方法里加个 return false,就是组织超链接点击时的跳转行为了;
document.oncontextmenu = function(){
//在这里可以加一些代码,实现自定义的右键菜单;
return false //系统自带的右键菜单就失效了
}
Form.onsubmit = function(){return false;}//这样表单就不会产生提交行为了;
document.onmousewheel = function(){return false;}//IE和chrome的方式,取消鼠标的滚轮的默认行为,网页的滚动条就不会动了;
document.addEventListener('DOMMouseScoll',function(e){e.preventDefault = true;});
火狐的取消滚轮的默认行为;火狐只能用Dom的二级事件绑定方式,并且用e.preventDefault = true;来取消浏览器滚轮的默认行为;
我们要知道常见的事件默认行为有哪些,并且要知道阻止默认行为,只要绑定到这个行为事件的方法最后加一句:return false;就可以了;
但是要强调的是:如果你的事件绑定是用addEventListener来实现的,那阻止默认行为必须用e.preventDefault = true;
当事件发生在子元素中的时候,往往会引起连锁反应,就是在它的祖先元素上也会发生这个事件,比如说你点击了一个div,也相当于点击了一个body,同样相当于点击了HTML,同样相当于点击了document,
一、是事件本身在传播,而不是绑定在事件上的方法在传播;
二、是并非所有的事件都会传播,像onfocus,onblur等事件就不会传播,onmouseenter和onmouseleave事件也不会传播。
事件委托是利用事件的传播机制,通过判断事件源来实现的,是一种高性能的事件处理方式。对事件委托的好处和概念详见《高程3》的第402页;
我们通过一个简单的示例来看看事件的好处。
需求:在如下的HTML代码中,当你点击这个页面中的一个元素时,弹出这个元素对应的标签名;
<body>
<div id='outer'>
outer
<div id = 'inner'>
inner
<p>ppppp
<span>span
<a href='###'>张松</a>
</span>
</p>
</div>
</div>
</body>
一般的思路是把所有的元素都获取到,然后循环绑定,这样做的缺点就是不仅性能不好,并且还要处理事件传播的问题,不优化的代码如下;
var eles = document.getElementsByTagNmae('*');
for(var i=0;i<eles.length;i++){
eles,item(i).onclick = function(e){
alert(this.tagName);
e.stopPropagation();//加上阻止事件传播是可以的,但是性能不是最优的;
return false;//阻止超链接的默认行为;
}
}
以下用事件委托实现
事件委托:事件委托就是利用事件传播的机制,无论哪一个页面元素,他的click事件都会最终传播到document上;这样,只需要在document上处理click事件即可;
document.onclick = function(e){
e = e||window.event;
var target = e.target||e.srcElement;//获得事件源是关键;
alert(target.nodeName);
return false;
};
DOM 是解决文档里元素关系的一套模式,其实那只是dom的第一个版本解决的问题。在dom的第二个版本里,解决的问题就不仅仅是文档里元素之间的关系了,还把dom元素的事件问题也重新给了一套方案,这套方案就叫做’dom二级事件‘;
DOM二级事件解决了原来的同意事件绑定多个处理方法时,后面绑定的会覆盖前面绑定的问题,如:
ele.onclick = fn1;
ele.onlcik=fn2;
这样的处理的结果就是,ele的onclick事件上,fn2方法把fn1方法给覆盖了,这样就不容易实现同一个事件上绑定多个方法。
W3C给出的方法是:ele.addEventListener('click',fn,false);
ie6/7/8给出的方法是:ele.attachEvent('onclick',fn);
解决标准浏览器和低版本的IE方案如下:
function bind(ele,type,handler){//标准浏览器
if(ele.addEventListener){
ele.addEventListener('type',handler,false);
}else if(ele.attachEveent){//IE专用
ele.attachEvent('on'+type,handler)
}
}
function unbind(ele,type,handler){
if(ele.removeEventListener){
ele.removeEventListener('type',handler,false);
}else if(ele.detachEvent){
ele.detachEvent('on'+type,handler);
}
}
注意:虽然IE、谷歌、火狐等浏览器都给出了DOM2级事件的处理方法,但是IE的方法却存在着很多问题,并且非常严重。一、被绑定的方法在事件触发执行时,this关键字竟让是window,二、IE中被绑定到事件上的方法的执行顺序是混乱的。
在W3C的标准是在同一事件上,先绑定的方法先执行,并且不能重复绑定同一个方法在同一个事件上,但是IE6、7、8中,如果绑定的方法少于9个,执行的顺序是相反的,超过9个,执行顺序就是混乱的,这些IE中的问题都是比较严重的,我们必须解决好。