想要清楚的对javascript的事件有一个详细的了解,我们必须搞明白以下几件事情:
首先,必须明白以下几个概念
什么是事件? 什么是事件处理程序? 事件类型有哪些?事件流?事件冒泡?事件捕获?事件对象? 常见浏览器兼容问题怎么解决?
事件的概念
javas使我们有能力创建动态页面,事件是可以被浏览器侦测到的行为,比方说,我们可以在用户点击某一个按钮的时候产生一个onclick来触发某个函数,常见的事件有click,load,unload等
事件处理程序
响应某个事件的函数则称为事件处理程序,或者叫做事件侦听器。
click、mousemove、load等都是事件的名称,事件处理程序就是在事件的前面加上“on”,click事件的事件处理程序为onclick。
事件类型
1.鼠标事件:
- click:单击
- dbclick:双击
- mousedown:当用户鼠标还未弹起触发
- mouseup:当用户释放按钮时触发
- mouseover:当鼠标移到某个元素上方时触发
- mouseout:当离开元素上方时触发
- mousemove:当鼠标指针元素时触发
2.键盘事件:
- keydown:当用户按键盘上任意键触发
- keypress:当用户按键盘上的字符键触发
- keyup:当用户释放键盘上的键触发
3.HTML事件
- load:当整个页面加载完成
- unload:当页面完全卸载后在window上面触发,或在框架集卸载后在框架集上触发
- select:当用户选择文本框(input/textarea)中的一个或多个字符事触发
- change:当文本框(input/textarea)内容且焦点后触发
- focus:当页面或元素焦点后在window及相关元素上触发
- blur:当页面或元素失去焦点时在window及相关元素上触发
- submit:当用户点击提交按钮时在form上触发
- reset:当用户点击重置按钮时在form上触发
- resize:当窗口或框架的大小发生变化时在window或框架上触发
- scroll:当用户滚动带滚动条的元素时触发
4.滚轮事件:mousewheel(IE6+均支持)、DOMMouseScroll(Firefox支持的,与mousewheel效果一样)。是使用鼠标滚轮时触发的。
事件流
事件流描述的是从页面中接收事件的顺序,对于事件流,IE与NetScape提出了完全相反的顺序,IE提出的是事件冒泡流,即事件开始的时候由最具体的接收,逐级向上传播较为不具体节点;网提出的时间捕获流,即事件由最不具体的开始接收,然后逐级向下传播到最具体的节点
window.onload= function(){
document.onclick=function(){
alert('document');
}
document.documentElement.onclick = function(){ //documentElement 属性可返回文档的根节点。
alert('html');
}
document.body.onclick=function () {
alert('body');
}
document.getElementById('box').onclick= function(){
alert('div');
}
document.getElementsByTagName('input')[0].onclick= function(evt){
alert('input');
//var e=evt||window.event;
//e.stopPropagation(); //W3C取消事件冒泡
//e.cancleBubble=true; //IE取消事件冒泡
//alert(typeof e.stopPropagation);
stop(evt);
}
}
//兼容(取消事件冒泡)
function stop(evt){
var e=evt||window.event;
if (typeof e.stopPropagation=='function') {
e.stopPropagation();
}else{
e.cancleBubble=true;
}
}
事件对象
在触发DOM上的某个事件的时候,会产生一个事件对象event,而在这个对象中包含着所有与事件有关的信息,其中有两个信息是我们最常用,分别是type和target,type表示的被触发事件的类型,target表示的是事件的目标
//支持的DOM的浏览器可以直接获取event;IE通过window.event获取
document.onclick = function(evt){
//var e=event||window.event; //跨浏览器获取event
// alert(e.type) //click
alert(getTarget(evt));
}
//跨浏览器获取event目标
function getTarget(evt){
var e = event||window.event;
return e.target||e.srcElement;
}
事件绑定
1.传统事件绑定(包括内联模型和脚本模型)
脚本模型
//问题一:会覆盖
window.onload = function(){
alert('li'); //被覆盖了
}
window.onload=function(){
alert('lii'); //前者被覆盖了 打印出lii
}
----------
解决覆盖问题
//alert(typeof window.onload); //一开始没有注册window.onload 那么就是null
window.onload = function(){
alert('li'); //被覆盖了
}
if (typeof window.onload=='function') { //判断是否存在上一个事件
var saved=null;
saved = window.onload; //保存上一个事件对象
};
//alert(typeof window.onload); //如果已经有window.onload 那么返回的就是一个函数 所以可以进行判断
window.onload=function(){
if(saved)saved(); //执行上一个事件window.onload=function(){};
alert('meiling'); //执行本事件
}
2.现代事件绑定(DOM2级模型)
//W3C自带的两个添加事件和删除事件
//1.解决覆盖问题
window.addEventListener('load',function(){
alert('lee');
},false) //lee
window.addEventListener('load',function(){
alert('le'); //le
},false)
//解决相同函数屏蔽的问题
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
window.addEventListener('load',init,false);
function init(){
alert('lee'); //只会弹出一个lee
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="script.js"></script>
<style type="text/css"> .red{ width: 100px; height: 100px; background-color: red; } .blue{ width: 200px; height: 200px; background-color: blue; } </style>
</head>
<body>
<div id="box" class="red">测试</div>
</body>
</html>
//3.是否可以传递this(可以传递)
//js部分
window.addEventListener('load',function(){
var box = document.getElementById('box');
box.addEventListener('click',toBlue,false);
},false);
function toRed(){
this.className='red';
this.removeEventListener('click',toRed,false)
this.addEventListener('click',toBlue,false);
}
function toBlue(){
this.className='blue';
this.removeEventListener('click',toBlue,false)
this.addEventListener('click',toRed,false);
}
//4.添加一个额外的方法会不会被覆盖,或者只能执行一次
window.addEventListener('load',function(){
var box = document.getElementById('box');
box.addEventListener('click',function(){
alert('lee');
},false);
box.addEventListener('click',toBlue,false);
},false);
function toRed(){
this.className='red';
this.removeEventListener('click',toRed,false)
this.addEventListener('click',toBlue,false);
}
function toBlue(){
this.className='blue';
this.removeEventListener('click',toBlue,false)
this.addEventListener('click',toRed,false);
}
IE事件处理函数
//IE事件处理函数 attachEvent() detachEvent()
//ie不支持捕获,只支持冒泡, ie添加事件不能屏蔽重复的函数, ie中的this指向的是window而不是DOM对象
//1.覆盖问题 ,解决了 但有不同 ,顺序不同 倒过来的
window.attachEvent('onload',function(){
alert('leee');
})
window.attachEvent('onload',function(){
alert('lee');
})
window.attachEvent('onload',function(){
alert('le');
})
//2.相同函数屏蔽的问题 未解决 无法屏蔽
window.attachEvent('onload',init);
window.attachEvent('onload',init);
function init(){
alert('lee'); //弹出两个lee
}
//3.是否可以传递this
window.attachEvent('onload',function(){
var box = document.getElementById('box');
box.attachEvent('onclick',function(){
// alert(this===box); //false
alert(this===window); //不能传递this true
})
})
// 4.添加一个额外的方法会不会被覆盖,或者只能执行一次 解决了
window.attachEvent('onload',function(){
var box = document.getElementById('box');
box.attachEvent('onclick',function(){
alert('lee');
});
box.attachEvent('onclick',function(){
alert('le');
});
})
IE和w3c兼容事件切换器
//跨浏览器添加事件
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(evt){
if (evt.target) { //w3c
return evt.target;
}else if(window.event.srcElement){ //IE
return window.event.srcElement;
}
}
addEvent(window,'load',function(){
var box = document.getElementById('box');
addEvent(box,'click',toBlue);
})
function toRed(evt){
var that = getTarget(evt);
that.className='red';
removeEvent(that,'click',toRed);
addEvent(that,'click',toBlue);
}
function toBlue(evt){
var that = getTarget(evt);
that.className='blue';
removeEvent(that,'click',toBlue);
addEvent(that,'click',toRed);
}
其它
//跨浏览器添加事件
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 preDef(evt){
var e =evt||window.event;
if (e.preventDefault) {
e.preventDefault();
}else {
e.returnValue = false;
}
}
//上下文菜单事件:contextmenu(很常用) ,当我们右击网页的时候会出现windows自带的菜单
//那么我们可以使用contextmenu事件来修改我们指定的菜单,但前提是把右击的默认行为取消掉
addEvent(window,'load',function(){
var text = document.getElementById('text');
addEvent(text,'contextmenu',function(evt){
preDef(evt);
var menu = document.getElementById('menu');
var e =evt||window.event;
menu.style.left=e.clientX+'px'; //得到鼠标的坐标
menu.style.top=e.clientY+'px';
menu.style.display='block';
addEvent(document,'click',function(){
menu.style.display='none';
})
})
})
//卸载前事件beforeunload,这个事件可以在帮助离开本页时给出相应的提示,‘离开’或‘返回’操作
addEvent(window,'beforeunload',function(evt){
preDef(evt);
})