浅谈JS事件处理程序

DOM0级事件处理程序


在标签内之间增加事件处理属性

<button id='btn1' onclick='hello()'>dom0级</button>
function hello(){alert('这是一个dom0级事件')};


使用该方法有两个弊端:
1、 需要分别为标签赋予onclick属性
2、 如果更改了绑定的函数,那么每个标签都需要修改,十分麻烦

DOM0级的另一种方法:直接在javascript代码中给DOM对象赋予onclick方法

document.getElementById('btn1').onclick=function(){
 alert("这是一个dom0级事件");}




DOM2级事件处理程序


DOM2级事件定义了两种方法:addEventListener和removeEventListener,分别实现增加和删除事件处理程序的操作。
这两种方法都接受三个参数:事件类型,事件函数,true/false
其中第三个参数:true代表事件捕获阶段,false代表事件冒泡阶段

 document.getElementById('btn2').addEventListener('click',function(){
     alert("这是一个dom2级事件");
        },false);//注意,这里的第一个参数没有加on



在这里有个坑,当我想要删除事件的时候使用

 document.getElementById('btn2').removeEventListener('click',function(){
     alert("这是一个dom2级事件");
         },false);

当我再次点击按钮的时候仍然会弹出对话框,原因是因为addEventListener和removeEventListener函数里的第二参数以匿名函数的形式存在,即便他们的功能一模一样,但是他们并不是同一个函数。

解决方法就是先将函数赋给一个变量

var handle=function(){alert('这是一个dom2级事件');}
document.getElementById('btn2').addEventListener('click',handle,false);
document.getElementById('btn2').removeEventListener('click',handle,false);

再次点击按钮发现没有弹出对话框。



IE事件处理程序


IE实现了类似的两个方法:attachEvent()和detachEvent()
这两种方法都接受两个参数,其中第一个参数为事件的类型,第二个参数为事件函数,需要注意的是第一个参数需要加on
IE事件并不需要接收第三个true/false参数,因为IE事件流只有事件冒泡没有事件捕获

document.getElementById('btn3').attachEvent("onclick",function(){
alert("这是一个兼容IE的事件");
});

和DOM2级一样,若要删除事件,第二个参数必须是同一个函数。

编写一个跨浏览器的事件处理程序

var eventUntil={
    addEvent:function(element,type,handle)
    {
        if(element.addEventListener)
        {
            element.addEventListener(type,handle,false);
        }
        else if(element.attachEvent)
        {
            element.attachEvent('on'+type,handle);
        }
        else element['on'+type]=handle;
    },
    removeEvent:function(element,type,handle)
    {
        if(element.removeEventListener)
        {
            element.removeEventListener(type,handle,false);
        }
        else if(element.detachEvent)
        {
            element.detachEvent('on'+type,handle);
        }
        else element['on'+type]=null;
    }
        }

在这里创建了一个eventUntil对象,为它提供了两个方法addEvent和removeEvent
在这里有两个地方需要注意:
(1)判断浏览器是否拥有该方法不需要加( )
(2)代码倒数第三行并没有使用"element."的形式,因为需要使用加号去拼接on和type:'on'+type,这样才能正确地向事件处理程序传递onclick这样的事件。使用方括号表示法可以解决属性名中包含会导致语法错误的字符或者属性名使用的是关键字或保留字的问题:element['on'+type]。

var handle=function(){alert('这是一个兼容浏览器的事件');}
eventUntil.addEvent(document.getElementById('btn3'),'click',handle);
eventUntil.removeEvent(document.getElementById('btn3'),'click',handle);




事件对象


在触发DOM上的某个事件时,会产生一个事件对象event,包含所有与事件有关的信息。

事件对象比较常用的属性和方法:

  1. type:事件类型
  2. target:事件目标
  3. preventDefault():取消事件的默认行为,如跳转链接
  4. stopPropagation():取消事件的进一步捕获或冒泡
<div id='father'>
<a href="http://www.baidu.com" id='son'>跳转</a>
</div>
eventUntil.addEvent(document.getElementById('father'),'click',function(){alert('我是父亲')});
eventUntil.addEvent(document.getElementById('son'),'click',function(e){alert('我是儿子');

当点击链接的时候会弹出‘我是儿子’对话框,紧接着又会弹出‘我是父亲’对话框。这是因为当点击链接触发事件后又会向上传播到父层触发父层的事件,这就是事件冒泡。再关比父层弹出的对话框后紧接着页面会跳转到百度,这就是浏览器的默认行为。



IE事件对象


  1. window.event:获取事件
  2. type:事件类型
  3. srcElement:事件目标
  4. returnValue:true(默认值,允许默认行为)/false(取消默认行为)
  5. cancelBubble:true(取消事件冒泡)/false(默认值,允许事件冒泡)



跨浏览器的事件对象


给eventUntil对象新添加如下属性和方法

getEvent:function(event){return event||window.event},
getTarget:function(event){return event.target||event.srcElement;},
stopPro:function(event)
{
        if(event.stopPropagation)//判断是否存在方法不需要加()
        {
            event.stopPropagation();
        }
    else event.cancelBubble=true;
},
preventDe:function(event)
{
        if(event.preventDefault)
        {
            event.preventDefault();
        }
        else event.returnValue=false;//IE
},

再来测试一下

eventUntil.addEvent(document.getElementById('father'),'click',function(){alert('我是父亲')});
eventUntil.addEvent(document.getElementById('son'),'click',function(e){alert('我是儿子');
e=eventUntil.getEvent(e);
eventUntil.stopPro(e);
eventUntil.preventDe(e);

eventUntil.stopPro(e)取消了事件冒泡,因此父层的对话框不会再弹出。
eventUntil.preventDe(e)取消了浏览器的默认行为,因此点击链接后不会跳转。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容

  • JavaScript 程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发...
    劼哥stone阅读 1,248评论 3 11
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,067评论 25 707
  • 1、窗体 1、常用属性 (1)Name属性:用来获取或设置窗体的名称,在应用程序中可通过Name属性来引用窗体。 ...
    Moment__格调阅读 4,428评论 0 11
  • 从前的时光,过去了就过去了,永远没有再回来的可能,被浸染的发丝,也就不可能再染回,时光于我,就如纸上的光阴,终归时...
    彧蒍阅读 192评论 0 1
  • 所有爱情都是现代史。 很久以前,白娘子和许仙、林黛玉和贾宝玉、张君瑞和崔莺莺。 她们历尽磨难仍一往情深。以情化泪一...
    幽明刘旭音阅读 186评论 0 4