事件绑定有两种,传统事件绑定,现代事件绑定。传统事件绑定有内联模式和脚本模式。脚本模式即把一个函数体赋给一个对象的事件属性。
window.onload=function()
{
var domb=document.getElementById('bd');
domb.onclick=function(){
alert('按钮点击');
};
};
传统事件绑定存在的问题:
1.同一个对象的事件属性多个函数赋值很多次,前面的会被覆盖掉,只显示最后一个。
解决方法,把第一个函数的事件保存下来,然后再去执行一次。
window.onload=function(){
alert('q');
};
if(typeof window.onload=='function')
{
var saved=null;
saved=window.onload;
}
window.onload=function(){
saved();
alert('s');
};
2.同一个事件类型下,不同事件的切换
解决方法: 当执行了第一个事件后,把第二个事件在第一个事件函数中赋值给点击事件。
把添加事件封装在一个函数中去。并且一并解决上述问题。
//一个对象里面的键值对,也可以用数组形式访问,属性放在中括号里。一个事件函数,里面不应该再放同名的//事件函数。
function addEvent(obj,type,fn)
{
var saveEvent=null;
if(typeof obj['on'+type]=='function')
saveEvent=obj['on'+type];
obj['on'+type]=function(){
if(saveEvent)
saveEvent();
fn.call(this);
};
}
添加事件后必须移除,不然内存会溢出
//删除事件
function removeEvent(obj,type)
{
if(obj['on'+type])
obj['on'+type]=null;
}
存在的问题:
1.如何避免添加已经添加过的函数。需要遍历事件,重名不添加。
2.删除事件时候,精确删除某个对象,某个类型,某个名称的函数。避免误删。
关于现代事件绑定,W3c自带两个事件添加删除函数
addEventListener removeEventListener
window.addEventListener('load',function
()
{
alert('w3c');
},false
);
可以解决
1.多个函数添加到同一个事件类型下被覆盖的问题
window.addEventListener('load',function
()
{
alert('w3c');//最先被执行的代码
},false
);
window.addEventListener('load',function
()
{
alert('w3把');
},false
);
window.addEventListener('load',function
()
{
alert('w3c5茶');//最后被执行的代码
},false
);
冒泡执行顺序,从最上面的代码开始往下执行,并且不会覆盖,每个事件都会被执行到。
2.解决了重复添加同一个函数的判定问题
window.addEventListener('load',fun,false
);
window.addEventListener('load',fun,false
);
function fun()
{
alert('lee');
}
只会被执行一次,相同函数,重复添加,会只显示一个,其他的被屏蔽掉。
3.解决了this指针传递的问题
window.addEventListener('load',function(){
var box=document.getElementById('box');
box.addEventListener('click',function()
{
alert(this);
},false);
},false
);
在现代事件函数中,第二个参数是函数,该函数内的指针指的是它添加的对象,但是在传统事件指的是window必须手工添加指针传递。
冒泡与捕获
window.addEventListener('load',function
()
{
var box=document.getElementById('box');
box.addEventListener('click',function()
{
alert(this);
},true);
document.addEventListener('click',function()
{
alert(this);
},true);
},false
);
冒泡就是对于不同的dom对象,如果添加了同一个类型的事件,从内到外的顺序执行事件,div先执行,document后执行。捕获是从外到内的顺序执行事件。document 先执行,div后执行。
IE自带的添加删除事件方法
attachEvent detachEvent
window.attachEvent('onload',function(){
alert('le');//最后执行的代码
}};
window.attachEvent('onload',function(){
alert('la');//最先执行的代码
}}
添加多个事件函数执行顺序和其它现代方法不一样,她是从下到上执行。
只能冒泡,不能判断重复添加的事件函数,不能传递this指针,指针默认指向window
解决方案:获取点击事件指针
var that=window.event.srcElement;
ie现代事件绑定方法可以将事件作为参数传递进去,传统方法不能把事件作为函数参数传递。
window.attachEvent('onload',function(evt){
alert(evt);
}};
ie和其他浏览器添加事件移除事件捕获事件对象的兼容性解决
//添加事件兼容性解决
function addEvent(obj,type,fn)
{
if(obj.addEventListener)
obj.addEventListener(type,fn,false);
else if(obj.attachEvent)
obj.attachEvent('on'+type,fn);
}
//移除事件兼容
function removeEvent(obj,type,fn) { if(obj.removeEventListener) obj.removeEventListener(type,fn,false); else if(obj.detachEvent) obj.detachEvent('on'+type,fn); }
//获取目标事件
function getTarget(e){ if(e.target) return e.target; else if(window.event.srcElement) return e.srcElement; }
获取事件中那个主对象旁边的离得最近相关对象
w3c标准
addEvent(window,'load',function()
{
var spanDom=document.getElementById('box');
addEvent(spanDom,'mouseover',function(e)
{
alert(e.relatedTarget);
}
);
}
);
ie标准的方法
ie标准的相关对象,鼠标移入mouseover 必须对应fromElement()鼠标移出mouseout 必须对应toElement()
addEvent(window,'load',function()
{
var spanDom=document.getElementById('box');
addEvent(spanDom,'mouseout',function(e)
{
alert(window.event.toElement);
}
);
}
);
两款浏览器兼容性解决
//两款浏览器兼容性解决
function getRelatedElement(e){
var e=e.relatedTarget||window.event;
if(e.srcElement)
{
if(e.type=='mouseover')
return e.fromElement;
if(e.type=='mouseout')
{
return e.toElement;
}
}
else if(e.relatedTarget)
{
return e.relatedTarget;
}
}
用传统方式阻止浏览器默认行为
addEvent(window,'load',function()
{
var a=document.getElementsByTagName('a')[0];
a.onclick=function(){
alert('qwe');
return false;
};
}
);
w3c阻止默认行为
addEvent(window,'load',function()
{
var a=document.getElementsByTagName('a')[0];
addEvent(a,'click',function(e){
e.preventDefault();
alert('qaaa');
});
}
);
阻止默认行为的兼容
//阻止默认行为的兼容
function preventDft(e)
{
var e=e||window.event;
if(e.preventDefault)
e.preventDefault();
else
e.returnValue=false;
}
上下文菜单事件
addEvent(window,'load',function()
{
var t=document.getElementsByTagName('textarea')[0];
addEvent(t,'contextmenu',function(e){
preventDft(e);
var menu=document.getElementById('menu');
menu.style.display='block';
menu.style.left=e.clientX+'px';
menu.style.top=e.clientY+'px';
});
}
);
卸载前事件,关于离开当前页面的事件
addEvent(window,'beforeunload',function(e)
{
preventDft();
});
关于鼠标滚轮事件
//对于非火狐浏览器
addEvent(document,'mousewheel',function(e)
{
alert(e.wheelDelta);//滚轮滚动度数
});
//对于火狐浏览器
addEvent(document,'DOMMouseScroll',function(e)
{
alert(e.detail);//滚轮滚动度数
});
DOMContentLoaded readystatechange两个事件关于加载性能