点击label时click事件被触发两次的坑

摘要:
3423432432432432<6 document.getElementById(“test”).onclick=function(ev){7 console.log(ev.target);3varelm=ev.target||ev.srcElement;i<len;window.XMLHttpRequest;hasInput(elm;

今天帮群里的朋友看一段代码的时候偶然间遇到一个label的坑,点击label的时候,监听的click事件被执行两次;

具体代码如下:

1   <div id="test">
2       <input type="checkbox" name="abc" id="abc"/>
3       <label for="abc">3423432432432432</label>
4    </div>
5    <script type="text/javascript">
6       document.getElementById("test").onclick = function(ev) {
7           console.log(ev.target);
8       }
9   </script>    

在控制台我们可以看到:

点击label时click事件被触发两次的坑第1张触发的事件源分别为input和label;

触发条件很简单:

  1、监听的是label和input的上层元素click事件

  2、label和input关联(for或者input在label下)

问题原因::

点击label的时候,事件冒泡一次,同时会触发关联的input的click事件,导致事件再次冒泡

解决方案:

  1、不用label(最简单直接粗暴的方法),如果为了语义化或者是个人习惯又不得不用label标签,那就继续往下看

  2、咱只认input,判断事件源为input,具体代码如下:

1     document.getElementById("test").onclick = function(e) {
2         var ev = e || window.event;
3         var elm = ev.target || ev.srcElement;
4         if (elm.tagName === 'LABEL') {return;}
5         // do something;
6     }

  上面代码受场景限制,即当input和label不关联的时候,点击label不作处理就会出现新的bug,所以改进如下:

 1     /**
 2      * 是否包含某id的input后代元素
 3      * @param  {Element}  elm 要判断的元素
 4      * @param  {String}   id  要匹配的id
 5      * @return {Boolean}
 6      */
 7     function hasInput(elm, id) {
 8         for (var i = 0, inputs = elm.getElementsByTagName("input"), len = inputs.length; i < len; i++) {
 9             if (inputs[i].id === id) {return true;}
10         }
11         return false;
12     }
13     /**
14      * 判断某元素下的label是否有关联的input
15      * @param  {Element}  elm    要判断的元素
16      * @param  {Element}  label  label元素
17      * @return {Boolean}
18      */
19     function isLabelhasRelativeInput(elm, label) {
20         if (label.getElementsByTagName("input").length) {
21             return true;
22         }
23         var forT = label.getAttribute("for");
24         var isIE6 = !-[1,] && !window.XMLHttpRequest;// IE6不支持for属性
25         if (forT && hasInput(elm, forT) && !isIE6) {
26             return true;
27         }
28         return false;
29     }
30     document.getElementById("test").onclick = function(e) {
31         var ev = e || window.event;
32         var srcElm = ev.target || ev.srcElement;
33         if (srcElm.tagName === 'LABEL' && isLabelhasRelativeInput(this, srcElm)) {return;}
34         // do something;
35     }

  顿时不开心了,代码变的这么长,修正了上述问题,通用性会更强一些了

3:祭出终极解决方案

1     var evTimeStamp = 0;
2     document.getElementById("test").onclick = function(e) {
3         var now = +new Date();
4         if (now - evTimeStamp < 100) {
5             return;
6         }
7         evTimeStamp = now;
8         console.log(2);
9     }

  通过事件触发的时间戳来判断,其实和事件冒泡有关的问题都可以通过该方法去处理。安全无公害

  最后给大家推荐下我们的群: 159758989无水js技术群,欢迎热爱前端的朋友加入

免责声明:文章转载自《点击label时click事件被触发两次的坑》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux网络编程 select/epoll得知socket有数据可读,如何判断数据全部被读取完毕?IDEA导入Git项目后右键项目找不到Git选项的解决方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

解决echarts图形由于label过长导致文字显示不全问题

使用echarts 打印饼图,在pc没问题,但一到移动端问题就来了,由于屏幕过小,导致label部分被遮挡 一、问题分析 如上图这个就尴尬了,囧么办呢?还好echarts 提供了formatter方法 二、修改前代码块 series: [ { name: seriesName || '数据来源', type:...

详解 Interpolator动画插值器

Interpolator 被用来修饰动画效果,定义动画的变化率。在Android源码中对应的接口类为TimeInterpolator,通过输入均匀变化的0~1之间的值,可以得到匀速、正加速、负加速、无规则变加速等0~1之间的变化曲线。 曲线举例: 如下图所示,为Android源码中OvershootInterpolator插值器变化率曲线。输入为均匀变化0...

从零开始编写自己的C#框架(12)——T4模板在逻辑层中的应用(一)(附源码)

对于T4模板很多朋友都不太熟悉,它在项目开发中,会帮我们减轻很大的工作量,提升我们的开发效率,减少出错概率。所以学好T4模板的应用,对于开发人员来说是非常重要的。   园子里对于T4模板的介绍与资料已经太多了,所以在这里我就不再详细讲述基础知识了,只是说说T4模板在本框架中的具体应用与实践。   一、创建逻辑层项目         二、添加引用      ...

C语言的面向对象设计 —— 对 X264/FFMPEG 架构探讨

类似题目的文章已经不新鲜了,这里,我仅仅总结自己的一些代码经验,结合两款在视频开发领域比较常用的开源软件探讨C语言的应用问题。 1.为什么要用C语言 曾几何时,我也不熟悉C,最早接触C的是在大学四年级,当时已经学过pascal,过二级也是pascal。接着走上了Delphi的路,多方便的软件,写写画画,程序就出来了,本科的毕业设计就是这样出来的MIS,在当...

Linux下iptables 禁止端口和开放端口

1、关闭所有的 INPUT FORWARD OUTPUT 只对某些端口开放。下面是命令实现: iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP 再用命令 iptables -L -n 查看 是否设置好, 好看到全部 DROP 了 这样的设置好了,我们只是临时...

sql server中调用c#写的dll里的方法

最近有一项目:  一超市管理系统单机版,运行在WIN2003+SQL2005上,每天超市关门都都会关电脑,现客户要新加功能,每天关门下班后回家可以上网查看超市管理系统的数据库里的相关数据,然后再做一些原系统没有的统计分析等,老系统不能做大改动,像升级到WIN2012+SQL2012等这些操作,改动越小越好。 现在的想法是:阿里云买台服务器,装上SQL,然...