JavaScript事件列表 | ||
事件 | 解说 | |
一般事件 | onclick | 鼠标点击时触发此事件 |
ondblclick | 鼠标双击时触发此事件 | |
onmousedown | 按下鼠标时触发此事件 | |
onmouseup | 鼠标按下后松开鼠标时触发此事件 | |
onmouseover | 当鼠标移动到某对象范围的上方时触发此事件 | |
onmousemove | 鼠标移动时触发此事件 | |
onmouseout | 当鼠标离开某对象范围时触发此事件 | |
onkeypress | 当键盘上的某个键被按下并且释放时触发此事件. | |
onkeydown | 当键盘上某个按键被按下时触发此事件 | |
onkeyup | 当键盘上某个按键被按放开时触发此事件 | |
页面相关事件 | onabort | 图片在下载时被用户中断 |
onbeforeunload | 当前页面的内容将要被改变时触发此事件 | |
onerror | 出现错误时触发此事件 | |
onload | 页面内容完成时触发此事件 | |
onmove | 浏览器的窗口被移动时触发此事件 | |
onresize | 当浏览器的窗口大小被改变时触发此事件 | |
onscroll | 浏览器的滚动条位置发生变化时触发此事件 | |
onstop | 浏览器的停止按钮被按下时触发此事件或者正在下载的文件被中断 | |
oncontextmenu | 当弹出右键上下文菜单时发生 | |
onunload | 当前页面将被改变时触发此事件 | |
表单相关事件 | onblur | 当前元素失去焦点时触发此事件 |
onchange | 当前元素失去焦点并且元素的内容发生改变而触发此事件 | |
onfocus | 当某个元素获得焦点时触发此事件 | |
onreset | 当表单中RESET的属性被激发时触发此事件 | |
onsubmit | 一个表单被递交时触发此事件 |
了解上面的事件如此简单,那么事件还有什么可讲的呢?
问题一:每个事件只能注册一个函数
var oDiv = document.getElementById("oDiv"); oDiv.onclick = fn1; oDiv.onclick =fn2; function fn1() {alert("我被覆盖了!")} function fn2() {alert("只有我被执行到!")}
解决方案一:
obj.onclick = function () { fn1(); fn2(); fn3(); };
缺陷一:需要将所有函数一次添加进去,不能在运行时添加
缺陷二:在事件处理函数中this将指向window,而不是obj
解决方案二:
function addEvent(fn,evtype,obj) { //obj是要添加事件的HTML元素对象 //evtype是事件名字,不包含on前缀,因为每个都有on,所以写个on是多余的 //fn是事件处理函数 var oldFn; if (obj["on"+evtype] instanceof Function) { oldFn = obj["on"+evtype];//当添加函数时,如果已注册过了,则将其保存起来 } obj["on"+evtype]=function () { if (oldFn) { oldFn.call(this); } fn.call(this);//使用call方法,使事件处理函数中的this仍指向obj }; }
这样已经解决了问题,但如何删除事件呢?如果直接将对象的onevtype这类的属性赋值为null将会删除所有的事件处理函数!
解决方案二的修改版:先将事件存储起来,存储在对象的__EventHandles属性里面
eventHandlesCounter=1;//计数器,将统计所有添加进去的函数的个数,0位预留作其它用 function addEvent(fn,evtype,obj) { if (!fn.__EventID) {//__EventID是给函数加的一个标识,见下面给函数添加标识的部分 fn.__EventID=eventHandlesCounter++; //使用一个自动增长的计数器作为函数的标识以保证不会重复 } if (!obj.__EventHandles) { obj.__EventHandles=[];//当不存在,也就是第一次执行时,创建一个,并且是数组 } if (!obj.__EventHandles[evtype]) {//将所有事件处理函数按事件类型分类存放 obj.__EventHandles[evtype]=[];//当不存在时也创建一个数组 if (obj["on"+evtype] instanceof Function) { //查看是否已经注册过其它函数 //如果已经注册过,则将以前的事件处理函数添加到数组下标为0的预留的位置 obj.__EventHandles[evtype][0]=obj["on"+evtype]; obj["on"+evtype]=handleEvents;//使用handleEvents集中处理所有的函数 } } obj.__EventHandles[evtype][fn.__EventID]=fn; //如果函数是第一次注册为事件处理函数,那么它将被添加到数组中,函数的标识作为下标 //如果函数已经注册过相同对象的相同事件了,那么将覆盖原来的而不会被添加两次 function handleEvents() { var fns = obj.__EventHandles[evtype]; for (var i=0;i< fns.length;i++) { fns[i].call(this); } } }
使用上面的函数已经可以在一个对象添加多个事件处理函数,在函数内部this关键字也指向了相应的对象,并且这些函数都被作了标识,那么移除某个事件处理函数就是轻而易举的了!
//使用传统方法:obj.onevtype = null;但这样会移除所有的事件处理函数 function delEvent(fn,evtype,obj) { if (!obj.__EventHandles || !obj.__EventHandles[evtype] || !fn.__EventID) { return false; } if (obj.__EventHandles[evtype][fn.__EventID] == fn) { delete obj.__EventHandles[evtype][fn.__EventID]; } }