javascript事件触发多个函数
javascript的核心之一就是处理事件,一般时候一个事件触发一个没参数的函数,如丝般顺滑,没毛病!
但是,在实际的使用中,一个事件经常需要触发多个函数:
var example=document.getElementById("example"); example.onmouseover=fontResize; example.onmouseover=colorChange; example.onmouseout=resetIt;
此时我们会发现onmouseover事件发生的时候只能触发colorChange函数运行,fontResize则毫无动静,另外这种方法无法为函数传参数。
事实上这是DOM Level 0对事件的规定决定的,事件作为对象的属性,在被赋值时前面的值会被覆盖,因此在实际触发时只有最后一个值被赋给了事件属性,这就是所谓的来得早不如来得巧啦^_^
在DOM Level 0下,大家普遍采用两种方法解决这个bug:
一、html属性赋值
不推荐,但是现在依然常用。
什么意思,就是直接在html内容里面设置事件和回调函数:
<a id="example" href="http://www.qingzz.cn/" onmouseover="fontResize("bigSize");colorChange("redColor");">迷津渡口</a>
这样调用非常方便,可以方便地添加参数,也可以调用多个函数,所有的bug貌似都消失了。
但是大多数大神都不推荐使用这种方法,原因是这种方法违反了js,css,html分开的原则。
有时我们小站怎么方便怎么来嘛,管你呢^_^
二、采用函数字面量
DOM Level 0下最受推崇的方法。
首先介绍一下何为函数字面量。
大家都知道,函数其实是可以作为右值赋给变量的:
function example () { alert("普通函数的函数名为函数字面量。"); } ex=example;//赋值
调用的时候使用ex()和example()是等价的,记住作为函数字面量的是函数名,不需要括号和参数。
另外一种函数字面量是没有名字的函数:
ex=function() {alert("无名函数也可以作为函数字面量。");};
调用时可以使用ex();
了解了函数字面量,有想法了没?
var example=document.getElementById("example"); example.onmouseover=function(){fontResize("bigSize");colorChange("redColor");}; example.onmouseout=resetIt;
发现了吧,这种方法可以说相对完美,添加参数和多个回调函数的问题都解决了。
但是,如果函数里面包含对象this,则函数就无法很好的运行了。
function fontResize(classSet) { this.className+=classSet; } function colorChange(classSet) { this.className+=classSet; }
平时没参数的单个函数使用this可以很方便获取对象,实际上还是有默认传递一个对象参数。
多个函数时,需要显式传递一个对象参数:
function fontResize(obj,classSet) { obj.className+=classSet; } function colorChange(obj,classSet) { obj.className+=classSet; }
调用函数时,传递this对象:
var example=document.getElementById("example"); example.onmouseover=function(){fontResize(this,"bigSize");colorChange(this,"redColor");}; example.onmouseout=resetIt;
函数方法addEventListener和attachEvent
其实在DOM Level 2里定义了专门用于为事件添加多个函数的方法:
obj.addEventListener(eventName,functionName,false);
第一个参数是事件名但是前面没有"on",例如"mouseover";
第二个参数是函数字面量,即函数名或者无名函数(带参数的只能通过这种);
第三个参数表示使用事件浮升,具体的可以不管啦^_^想知道的自己百度~
没参数的直接使用函数名:
var example=document.getElementById("example"); example.addEventListener("mouseover",fontResize,false); example.addEventListener("mouseover",colorChange,false); example.onmouseout=resetIt;
有参数的使用无名函数:
var example=document.getElementById("example"); example.addEventListener("mouseover",function(){fontResize("bigSize");},false); example.addEventListener("mouseover",function(){colorChange("redColor");},false); example.onmouseout=resetIt;
执行顺序可以说没特别的关系,也可以说是从前到后执行,但不用特别关注。
DOM Level 2出来之前,IE大哥已经自己搞了一套,那就是attachEvent,现在依旧沿用。
obj.attachEvent(eventName,functionName)
第一个参数是事件名,包含"on",即和原来一样,仍旧是例如"onmouseover"一类的。
第二个参数是函数字面量,即函数名或者无名函数(带参数的只能通过这种)。
没有第三个参数,因为默认为事件浮升。
没参数的直接使用函数名:
var example=document.getElementById("example"); example.attachEvent("onmouseover",fontResize); example.attachEvent("onmouseover",colorChange); example.onmouseout=resetIt;
有参数的使用无名函数:
var example=document.getElementById("example"); example.attachEvent("onmouseover",function(){fontResize("bigSize");}); example.attachEvent("onmouseover",function(){colorChange("redColor");}); example.onmouseout=resetIt;
因此为了保证兼容性,需要这么做:
没参数的直接使用函数名:
var example=document.getElementById("example"); if (document.addEventListener) { example.addEventListener("mouseover",fontResize,false); example.addEventListener("mouseover",colorChange,false); } else if (document.attachEvent) { example.attachEvent("onmouseover",fontResize); example.attachEvent("onmouseover",colorChange); } example.onmouseout=resetIt;
有参数的使用无名函数:
var example=document.getElementById("example"); if (document.addEventListener) { example.attachEvent("onmouseover",function(){fontResize("bigSize");}); example.attachEvent("onmouseover",function(){colorChange("redColor");}); } else if (document.attachEvent) { example.attachEvent("onmouseover",function(){fontResize("bigSize");}); example.attachEvent("onmouseover",function(){colorChange("redColor");}); } example.onmouseout=resetIt;
分享工具函数addEventHandler和getActivatedObject
function addEventHandler(obj,eventName,handler) { if (document.attachEvent) { obj.attachEvent("on"+eventName,handler); } else if (document.addEventListener) { obj.addEventListener(eventName,handler,false); } } function getActivatedObject(e) { var obj; if (!e) { // early version of IE obj=window.event.srcElement; } else if (e.srcElement) { // IE 7 or later obj=e.srcElement; } else { // DOM Level 2 browser obj=e.target; } return obj; }
使用方法:
在事件处理函数定义里无法使用this,而需要显式传递一个event参数,这个参数放在参数表的最后,事件处理函数会自动传递,不需要显式传递:
没其他参数的使用方法:
函数定义:
function fontResize(e) { var me=getActivatedObject(e); me.className+="bigSize"; } function colorChange(e) { var me=getActivatedObject(e); me.className+="redColor"; }
无参数事件处理函数使用:
var example=document.getElementById("example"); addEventHandler(example,"mouseover",fontResize); addEventHandler(example,"mouseover",colorChange); example.onmouseout=resetIt;
多参数的定义方法:
function fontResize(classSet,e) { var me=getActivatedObject(e); me.className+=classSet; } function colorChange(classSet,e) { var me=getActivatedObject(e); me.className+=classSet; }
多参数事件处理函数使用:
var example=document.getElementById("example"); addEventHandler(example,"mouseover",function(){fontResize("bigSize");}); addEventHandler(example,"mouseover",function(){colorChange("redColor");}); example.onmouseout=resetIt;
实际使用哪一种方法大家自己斟酌吧,推荐是最后一种方法啦,兼容性好。
本文写得太累了,拒绝转载,需要转载请联系站长^_^