JS为句柄添加监听函数

      具体谈如何实现JS为句柄添加监听函数之前先看一段代码,算是抛出这个问题。

1<html> 2<head> 3<title>JS为句柄添加监听函数</title> 4 5<script> 6    function message(){ 7 alert("hello!"); 8 } 9</script> 10</head> 11<body> 12 <center> 13     <div onclick="message();"><p>JavaScript</p></div> 14    </center> 15</body> 16</html>

        程序代码本身的运行是不会有问题的。不过我的着眼点在于CSS是为了让html文档结构和变现分离,JavaScript着眼于文档结构和行为的分离,上面带按摩并未做到文档结构和行为的彻底分离(div上指明了onclick事件)。

        接下来就是如何在js中实现对div添加onclick监听函数。

JS实现行为、结构分离

       其实在JavaScript中为DOM元素绑定事件监听函数是一件非常常见的事情,但是这里也有许多bug。各种浏览器对于事件的绑定都提供了很多的方法,但是可靠的只有3种:

传统绑定:

1<html><head> 2    <title>JS为句柄添加监听函数</title> 3 4    <script> 5        function message(message) { 6            alert(message); 7        } 8 9        window.onload = function() { 10            var div = document.getElementById("div"); 11            div.onclick = function(event) { 12                message(event.type); 13            }; 14        } 15    </script></head><body> 16    <center> 17        <div id="div"> 18            <p>JavaScript</p> 19        </div> 20    </center></body></html>

       A:传统的绑定方法,非常简单稳定,而且函数体内的this就是正在处理事件的节点。

       B:一个元素的事件句柄只能注册一个函数,重复注册会产生覆盖;而且传统的绑定只会在事件冒泡中运行。

       Tips:事件冒泡:当一个元素上的事件触发时,同样的事件会在该元素的所有祖先元素中触发。该事件从元素一直冒泡到DOM树的最上层,这一过程称为事件冒泡。

W3C标准绑定:

1<html><head> 2    <title>JS为句柄添加监听函数</title> 3 4    <script> 5        function message(message) { 6            alert(message); 7        } 8 9        window.onload = function() { 10            var div = document.getElementById("div"); 11 //注册监听函数 12            div.addEventListener('click',function(event){ 13 message(event.type+"  hello"); 14 },false); 15 //重复注册监听函数 16 div.addEventListener('click',function(event){ 17 message(event.type+"  world"); 18 },false); 19        } 20    </script></head><body> 21    <center> 22        <div id="div"> 23            <p>JavaScript</p> 24        </div> 25    </center></body></html>

      A、这种绑定方法同时支持事件处理的捕获和冒泡两个阶段;同一元素的同一事件句柄可以注册多个监听函数;而且内部this指向当前元素

            Tips:adEventListener中的第三个额参数为false(冒泡获取由里向外)|true(由外向里)

      B、我大IE不支持这种注册方法。

IE绑定:

1<html><head> 2    <title>JS为句柄添加监听函数</title>  <script> 3        function message(message) { 4            alert(message); 5        } 6 7        window.onload = function() { 8            var div = document.getElementById("div"); 9            //注册监听函数 10            div.attachEvent('onclick', 11                function() { 12                    message(window.event.srcElement.innerHTML + ' ' + this.innerHTML + 1); 13                } 14            ); 15            //重复注册监听函数 16           div.attachEvent('onclick', 17                function() { 18                    message(window.event.srcElement.innerHTML + ' ' + this.innerHTML + 2); 19                } 20            ); 21        } 22    </script></head><body> 23    <center> 24        <div id="div"> 25            <p>JavaScript</p> 26        </div> 27    </center></body></html>

       A:这种绑定方法,可以为同一事件句柄注册多次。

       B:IE的事件模型不支持事件捕获;监听函数体内的this指向的不表示当前元素,而且window.event.srcElement指向的是发生事件的节点,而不是当前节点。

       除了强烈的吐槽一下IE浏览器之外,我们也只能静下心来寻求一种兼容的方法了,接下来介绍两种方法:

跨浏览器方法一:

1function addEvent(element, type, handler) { 2      if (!handler.$$guid) handler.$$guid = addEvent.guid++; 3      if (!element.events) element.events = {}; 4      var handlers = element.events[type]; 5      if (!handlers) { 6        handlers = element.events[type] = {}; 7        if (element["on" + type]) { 8          handlers[0] = element["on" + type]; 9        } 10      } 11      handlers[handler.$$guid] = handler; 12      element["on" + type] = handleEvent; 13    }; 14    addEvent.guid = 1; 15     16    function removeEvent(element, type, handler) { 17      if (element.events && element.events[type]) { 18        delete element.events[type][handler.$$guid]; 19      } 20    }; 21    function handleEvent(event) { 22      var returnValue = true; 23      event = event || fixEvent(window.event); 24      var handlers = this.events[event.type]; 25      for (var i in handlers) { 26        this.$$handleEvent = handlers[i]; 27        if (this.$$handleEvent(event) === false) { 28          returnValue = false; 29        } 30      } 31      return returnValue; 32    }; 33     34    function fixEvent(event) { 35      event.preventDefault = fixEvent.preventDefault; 36      event.stopPropagation = fixEvent.stopPropagation; 37      return event; 38    }; 39    fixEvent.preventDefault = function() { 40      this.returnValue = false; 41    }; 42    fixEvent.stopPropagation = function() { 43      this.cancelBubble = true; 44    };

       参考:http://dean.edwards.name/weblog/2005/10/add-event2/

跨浏览器方法二:

1function addEvent( obj, type, fn ) { 2      if ( obj.attachEvent ) { 3        obj['e'+type+fn] = fn; 4        obj[type+fn] = function(){obj['e'+type+fn]( window.event );} 5        obj.attachEvent( 'on'+type, obj[type+fn] ); 6      } else 7        obj.addEventListener( type, fn, false ); 8    } 9    function removeEvent( obj, type, fn ) { 10      if ( obj.detachEvent ) { 11        obj.detachEvent( 'on'+type, obj[type+fn] ); 12        obj[type+fn] = null; 13      } else 14        obj.removeEventListener( type, fn, false ); 15    }

       参考::http://ejohn.org/projects/flexible-javascript-events/

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )