Javascript中的事件流(IE和W3C的区别)和事件委托

事件流是用来描述页面接收事件的顺序。目前存在的两种基本的事件流为事件冒泡和事件捕获

事件冒泡

即事件应该从嵌套层次最深的节点(目标元素节点)冒泡到较为不具体的节点(Document对象),所有的现代浏览器都支持事件冒泡,但是在IE5.5以及之前的版本事件冒泡会跳过html标签,也就是说会直接从body冒泡到Document,而在IE9,firefox,chrome和safari浏览器则会将事件一直冒泡到window对象上。

       <!DOCUMENT html>
       <html>
           <head>
               <title>HTML</title>
           </head>
           <body>
               <p id="click">Click</p>
           </body>  
       </html>

如果点击了p标签的元素,事件就会向上冒泡,依次为<p>,<body>,<html>,<Document>

事件捕获

即事件应该从不具体的节点先接收,然后再向更深层次的节点传播,以上述代码为例,如果是事件捕获,则Document对象会先捕获到事件,然后再沿着DOM树向下到html标签,body标签,最后到达p标签

IE事件流

1、IE事件流只支持事件冒泡,不支持事件捕获
2、IE事件流可以通过可以通过attachEvent()和detachEvent()来添加和删除事件,这两个方法只接受两个参数,依次为 (target,handler),事件类型("on"+事件类型),事件处理函数,需要注意的一点是在使用detachEvent()方法删除事件时,参数要和创建事件时的参数相同,即第二个参数不支持通过匿名函数来创建,否则会被视为不是同一个方法。
    const btn = document.getElementById("button");
    btn.attachEvent("onclick",function(){
          console.log("click");
    })

     btn.detachEvent("onclick",function(){
           console.log("click");
     })
     //删除失败,尽管两个匿名函数一样,但是在处理时会被识别为两个不同的函数对象
3、IE事件中的this指向的是window对象而不是目标元素对象,是因为在使用attachEvent()创建事件时,事件处理程序运行的作用于不是目标元素所在的作用域,而是在全局作用域中运行,所以this指向的是window而不是目标元素
4、在IE事件流中,如果为一个元素顺序绑定多个事件,事件执行的顺序是按照逆序执行的。
      const btn = document.getElementById("button");
      btn.attachEvent("onclick",function(){
          console.log("one");
      })

      btn.attachEvent("onclick",function(){
          console.log("two");
      })

       btn.attachEvent("onclick",function(){
          console.log("three");
      })

      //出发事件的运行结果为
      //three
      //two
      //one
5、IE事件中可以通过returnValue属性来阻止事件的默认行为,即将window.event.returnValue设置为false就可以阻止事件的默认行为,可以通过cancelBubble属性来停止事件的进一步传播,由于IE事件流只支持事件冒泡,所以该属性只能停止事件冒泡行为。

W3C事件流

1、W3C事件流支持事件捕获和事件冒泡
2、W3C事件流可以通过可以通过addEventListener()和removeEventListener()来添加和删除事件,这两个方法接受三个参数,依次为 (target,handler,boolean),事件类型,事件处理函数,布尔值(如果设置为false,表示该事件处理函数在事件冒泡阶段触发,如果设置为true,表示该事件处理函数在事件捕获阶段触发,事件冒泡阶段不再触发)需要注意的一点是在使用removeEventListener()方法删除事件时,参数要和创建事件时的参数相同,即第二个参数不支持通过匿名函数来创建,否则会被视为不是同一个方法(同IE事件流规则相同)。
3、W3C事件流中this指向的是目标元素的作用域,不同于IE事件处理程序的作用域为全局作用域,W3C事件流中的事件处理程序的作用域为目标元素所在的作用域,所以this指向的是目标元素。
4、在W3C事件流中,如果为一个元素顺序绑定多个事件,事件执行的顺序是按照顺序执行的。
      const btn = document.getElementById("button");
      btn.attachEvent("onclick",function(){
          console.log("one");
      })

      btn.attachEvent("onclick",function(){
          console.log("two");
      })

       btn.attachEvent("onclick",function(){
          console.log("three");
      })

      //出发事件的运行结果为
      //one
      //two
      //three
5、W3C事件中可以通过preventDefault()方法阻止事件的默认行为,可以通过stopPropagation()方法停止事件在DOM结构中进行传播,即停止事件继续冒泡或者捕获。
6、还可以通过event对象的eventPhase属性来判断事件处于哪一个阶段,调用event.eventPhase,如果返回值为1,则事件处于捕获阶段,如果返回值为2,则事件处于目标阶段,如果返回值为3,则事件处于冒泡阶段。

跨浏览器事件

   var EventUtil = {

        add:function(node,target,handler){
            if(node.addEventListener){
                node.addEventListener(target,handler,false);
            }else if(node.attachEvent){
                node.attachEvent("on"+target,handler);
            }else{
                node["on"+target] = handler;
            }
        },

        remove:function(node,target,handler){
            if(node.removeEventListener){
                node.removeEventListener(target,handler,false);
            }else if(node.detachEvent){
                node.detachEvent("on"+target,handler);
           }else{
               node["on"+target] = handler;
          }
        }
   }

   const btn = document.getElementById("button");
   EventUtil.add(btn,"click",function(){
       console.log("click");
   });

可以通过调用对象EventUtil中的属性来实现添加事件和删除事件,每个属性中通过if-else 来判断浏览器兼容的事件处理程序实现简单的跨浏览器事件调用。

事件委托

事件委托是为处理过多的事件处理程序而设计的,事件委托采用事件冒泡,也就是说,如果想要为一个元素的所有子节点都添加一个事件处理程序的话,只需要获取该父节点的DOM即可,如果想要冒泡到document,也可以直接在document对象上添加事件,而不需要给每一个子节点一个一个添加事件处理程序,以下以W3C事件为例子

         var btn = document.getElementById("button");
         btn.addEventListener("click",function(event){
                  let target = event.target;              
                  switch(target.innerHTML){
                       case  "one":
                           console.log("one");
                           break;
                       case "two":
                           alert("two");
                           break;
                       case:"three":
                           localtion.href = "www.greatytc.com";
                           break;
                       default:
                           alert("undefined");
                            
         },false)

使用事件委托,首先可以减少DOM操作,只需要获取最外层元素的节点即可,其次如果要对每一个元素都一一添加事件,会占用大量的内存,影响整个页面运行的性能,同时通过事件委托也可以提高添加事件的效率,上述实例仅通过switch-case语句就可以实现对于每一个子节点事件的添加,避免了使用一个个addEventListener()或者attachEvent()方法来为每一个子节点添加事件处理程序。

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

推荐阅读更多精彩内容