javascript 之事件处理函数和事件对象

本文主要谈及问题:

  • 关于编写跨浏览器的事件处理函数和事件对象

关于编写跨浏览器的事件处理函数和事件对象

  • 为什么要编写跨浏览器的事件处理函数和事件对象

近几年来,个人对WINDOWS越来越没爱。至于为什么无爱,我想原因有二:

  • 转投MAC阵营,觉得MAC比起WINDOWS对用户太友好了
  • 成为了一个前端工程师

讲讲第二点。网上一直流传着一个段子:IE都有勇气让你把它设为默认浏览器,为什么你还连表白的勇气都没有。每每看到这个段子,心都有点痛,我想不仅是我,每个前端工程师都会有这样的感觉。微软在IE9之前,完全是think different ,make 更加 different。做出来的东西完全跟标准不一致。FE们为了兼容它没少花心思。就拿事件模型来说,基本上最常用的模型有两种:一种是DOM L2 EVENT MODEL.另外一种不用说,相信大家都知道,就是IE EVENT.所以我们就被逼着编写跨浏览器的事件处理函数和事件对象。是不是觉得IE很作死,可是没办法啊,人家还占那么多份额,我们只能乖乖地兼容它。

  • 怎么编写跨浏览器的事件处理函数和事件对象

    • 事件处理函数

      • DOM 事件处理函数(这里只谈及DOM2)
        DOM2级事件定义了两种方法:

        • addEventListener(type,handler,useCapture); --添加事件处理函数
        • removeEventListener(type,handler,useCapture); -- 删除事件处理函数

        这两个方法都有三个参数:type为事件的类型,handler为事件处理程序的函数,userCapture(可选参数)为事件流类型,冒泡为false,捕获为true,默认为false。

      • IE 事件处理函数
        IE 事件定义了两种方法:

        • 添加事件处理函数 :attachEvent("on"+type,handler);
        • 删除事件处理函数 :detachEvent("on"+type,handler);

        这两个方法都有两个参数:第一个参数"on"+type是事件类型(如果在addEventListener的type为click,则此处应该为onclick),第二个参数handler为事件处理程序的函数。注意:IE8之前的浏览器只支持事件冒泡,不支持事件捕获。

      • 区别:

        • 一个元素添加多个事件处理函数的执行顺序:如果为一个元素添加多个事件处理函数,addEVentListener会按照添加的顺序执行代码。而attachEvent会按照添加顺序的相反顺序,如下:

          var btn = document.getElementById('btn');
          btn.addEventListener("click",function(){
          alert("1");
          });
          btn.addEventListener("click",function(){
          alert("2");
          });
          //以上代码先输出1,在输出2   
          
          var btn = document.getElementById('btn');
          btn.attachEvent("onclick"function(){
              alert("1");
          })
          btn.attachEvent("onclick"function(){
           alert("2");
          })
          //以上代码先输出2,再输出1
          
        • 事件处理程序的函数中的this:addEventListener的handler中的this指的是添加该事件处理函数的元素,而attachEvent的handler中的this指的是window对象。如下:

          var bt = document.getElementById("bt");
          bt.addEventListener("click",function(){
            console.log(this === bt)
          })    
          //为true,this指添加事件处理函数的元素
          var bt = document.getElementById("bt");
          bt.attachEvent("onclick",function(){
            console.log(this === window)
          })
          //为true,this指window对象
          
      • 跨浏览器事件处理函数 :
        综合上述的事件处理函数,我们可以写出跨浏览器的事件处理函数,我们可以把它包含在一个对象里。如下:

        var eventForAllBrowsers = {
              addHandler :function(elem,type,handler){
                  if(elem.addEventListener){
                      elem.addEventListener(type,handler,false);
                  } else if(elem.attachEvent){
                      elem.attachEvent("on"+type,handler);
                  } else{
                      elem["on"+type] = handler;
                      //加上对DOM 0 的支持
                  }
              },
              removeHandler:function(elem,type,handler){
                  if(elem.removeEventListener){
                      elem.removeEventListener(type,handler,false)
                  } else if(elem.detachEvent){
                      elem.detachEvent("on"+type,handler);
                  } else {
                      elem["on"+type] = null;
                  }
              }
        }
        
    • 事件对象
    在触发dom上的某个事件时,会产生一个事件对象event,这个对象中包含着所有与事件有关的信息,该对象在事件触发完毕后会被自动销毁。
    • DOM 事件对象
      兼容DOM的浏览器会将一个event对象传入到事件处理程序中。在函数内可以访问event对象的属性与方法。如下:
      var bt = document.getElementById('bt');
      bt.addEventListener("click",function(event){
      alert(event.type)
      })
      event对象中包含的常用的属性和方法:
      • preventDefault() --- 取消事件的默认行为。
      • stopPropagation() --- 取消事件的进一步冒泡。
      • type --- 被触发的事件的类型。
      • target --- 事件的目标。
    • IE 事件对象
      与兼容DOM的浏览器不同,要访问IE的event对象分两种情况:
      • 使用DOM 0 方法添加事件处理程序:在程序的函数内,用window.event去访问event对象。如下:

        var bt = document.getElementById('bt');
        bt.onclick = function(){
          var event = window.event;
          alert(event.type)
        }
        
      • 使用IE 事件处理函数:将event对象传入事件处理程序的函数内。如下:

        var bt = document.getElementById('bt');
        bt.attachEvent("onclick",function(event){
          alert(event.type)
        })
        

event对象中包含的常用的属性和方法:
- cacelBubble --- 默认值为false,将其设置为true就可以取消事件冒泡。
- returnValue --- 默认值为true,将其设置为false则可以取消事件的默认行为。
- srcElement --- 事件的目标。
- type --- 被触发事件的类型。

- 跨浏览器的事件对象
  通过检查兼容DOM的浏览器的event对象的方法和属性是否存在的方法去处理跨浏览器兼容性问题。把通用的事件对象的相关函数添加到eventForAllBrowsers上,代码大致如下:
      var eventForAllBrowsers = {
      //省略上述的代码
         getEvent :function(event){
                 return event ?event: window.event;
            },
            getTarget:function(event){
                return event.target || event.srcElement;
            },
            preventDefault:function(event){
                if(event.preventDefault){
                    event.preventDefault();
                }else{
                    event.returnValue = false;
                }
            },
            stopPropagation:function(event){
                if(event.stopPropagation){
                    event.stopPropagation();
                }else{
                    event.cancelBubble = true;
                }
            }         
      }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容

  • 以下文章为转载,对理解JavaScript中的事件处理机制很有帮助,浅显易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy阅读 3,030评论 1 10
  • JavaScript 程序采用了异步事件驱动编程模型。在这种程序设计风格下,当文档、浏览器、元素或与之相关的对象发...
    劼哥stone阅读 1,253评论 3 11
  • 什么是事件: 事件是交互体验的核心功能 一.事件冒泡: 当一个事件发生时,这个事件会从内向外逐层传递。 二.为什么...
    轻描淡写mua阅读 514评论 0 0
  • title: 实现通用的事件注册方法date: 2017-07-15tags: [原生js]categories:...
    始悔不悟阅读 1,039评论 0 0
  • 事件流: 事件流:页面接收事件的顺序。 IE定义的:事件冒泡流(由最具体的元素依次传播到DOM树的最上层的Docu...
    xiaoguo16阅读 580评论 0 0