click点击事件嵌套中的重复执行问题的根本原因

问题描述:

jQuery的点击事件中嵌套点击事件,当我们重复点击外层点击事件绑定的对象之后,再去点击内层的事件目标对象,我们就会遇到一个内层点击事件重复执行的问题。

(这个问题是在开发后台管理系统的时候遇到的,利用模态框增删改查之后进行确认时出现的问题,以下为一般探索过程,解决办法网上已经有很多,但是至于其真正产生的根本原因,有很多说得并不是很清楚,于是自己探索了一下。)

测试页面如下:

点击展开

 

重复点击5次之后再点击确认按钮

此时重复点击确认的话……

每点一下确认,内层的点击事件就会执行5次!!!

源码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    div{
        width: 200px;
        height:100px;
        background-color: #cfcfcf;
        line-height: 100px;
        display: none;
    }
</style>
<body>
    <button id="btn1">展开</button>
    <div><button id="innerBtn">确认</button></div>
    <script src="../../jQuery/jQuery v3.3.1.min.js"></script>
    <script>
        let i = 1;
        $(function(){
            $("#btn1").click(function(){
                $("div").show();
                $("#innerBtn").click(function(){
                    console.log(i++);
                })
            })
        })
    </script>
</body>
</html>

可以看到,重复点击5次展开/收起按钮之后再点击确认按钮是,控制台输出的结果为:1~5,也就是说内层的点击事件,在我点击确定的时候执行了5次。

网上的参考原因:发现每次点击外部的click事件后,内部的click事件都会绑定一次,因此会遍历很多次。

 

???什么???

这里乍一看,好像是那么回事儿,细一想却就有点不清不楚了,为什么会是这个样子?

首先,每次点击外部click事件目标对象后,内部的click事件都会绑定一次是什么意思?

各种查资料,最后却要追究到jQuery中的click和DOM中的onclick的区别上来

        DOM中的onclick是js原生的处理事件;

        jQuery中的click是其定义的一个方法,这个方法的本质是调用了DOM的onclick事件。

 

嗯……这和内部click事件多次绑定有什么关系吗?有,还真有:

如果我们将使用jQuery的代码改为原生的js,使用onclick来实现功能的话,就不存在以上的问题:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<style>
    div{
        width: 200px;
        height:100px;
        background-color: #cfcfcf;
        line-height: 100px;
        display: none;
    }
</style>
<body>
    <button id="btn1">展开</button>
    <div><button id="innerBtn">确认</button></div>
    <!-- <script src="../../jQuery/jQuery v3.3.1.min.js"></script> -->
    <script>
        let i = 1;
        // $(function(){
        //     $("#btn1").click(function(){
        //         $("div").show();
        //         $("#innerBtn").click(function(){
        //             console.log(i++);
        //         })
        //     })
        // })
        window.onload=function(){
            document.getElementById("btn1").onclick = function(){
                document.getElementsByTagName("div")[0].style.display = "block";
                document.getElementById("innerBtn").onclick = function(){
                    console.log(i++);
                }
            }
        }
    </script>
</body>
</html>

 

无论之前点了多少次展开按钮,当我们点击确认时,内层的点击事件都只执行一次。

 

那,这又是为什么呢? 

        又是一番查资料不提,刚刚看到了事件监听,也就是addEventListener,突然想起了addEventListener 与 onclick的区别,其中有一条,大概的意思就是:addEventListener可以给对象绑定多个事件处理程序,而onclick只能绑定一个 事件处理程序。

也就是说:当我们使用事件监听(addEventListener)的方式给元素添加事件处理程序的时候,其实使用的是类似于push和append的方式,也就是增加事件处理程序,而当我们使用onclick的时候,其实是在给元素对象设置事件处理程序,也即是没有就加上,有就覆盖

结合文章查看jQuery源代码不难发现,其实jQuery这货在绑定事件的时候,其实就是使用的addEventListener。

 

到这里,其实 “ 每次点击外部的click事件后,内部的click事件都会绑定一次,因此会遍历很多次。” 这句话,也就不那么难以理解了。

 

OK:

使用jQuery的click事件嵌套click,出现重复执行的原因,基本明朗了:

根本原因:

addEventListener重复绑定事件是增加 而不是覆盖!!

这就是:当我们点击外层click事件元素的时候,会执行其事件绑定的函数体,每点击一次就执行一次,而我们的外层点击事件的函数体内,又有绑定点击事件的语句时,相当于外层点击一次,内层就会给事件目标对象多加上一个点击事件。外层点击了多少次,内层事件目标对象就被绑定了多少个点击事件!!!所以才会在我们多次点击外层事件目标对象后再点击内层事件目标对象时,出现重复执行内层事件处理程序的情况。因为你本来就绑定了那么多次……

 

解决办法:

内层绑定事件之前,先解除事件目标对象上绑定的事件。

let i = 1;
$(function(){
    $("#btn1").click(function(){
          $("div").show();
          $("#innerBtn").off("click"); //解除绑定的点击事件
          $("#innerBtn").click(function(){
              console.log(i++);
          })
     })
})

当然,解除事件绑定的方法还有很多,这里就不一一列出,下次有空在详细探究一番。

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
for循环的嵌套使用是指在一个for循环的循环体嵌套另一个for循环。嵌套的for循环可以有多个层次,每个层次的循环体会在外层循环每次迭代时执行一遍。内层循环的执行次数等于各层循环执行次数的乘积。这种嵌套结构可以用来处理需要多次重复的任务,并且每次重复任务还有更小的重复任务需要执行的情况。在编程嵌套的for循环常用于遍历二维数组或执行多次嵌套的计算。 初学者在理解嵌套的for循环时可能会感到困惑,但有一种方法可以帮助理解。首先,先不看最外层的for循环,而是从内部的for循环开始分析。这样可以更容易理解内部循环的执行次数以及内部循环体的具体操作。然后再回过头来看最外层的for循环,这样会更清楚地明白整个嵌套循环的执行过程。 通过合理的嵌套for循环的运用,我们可以更高效地处理复杂的任务,提高程序的执行效率。当然,在使用嵌套for循环时,我们也需要注意代码的可读性和维护性,避免过多的嵌套导致代码难以理解和调试。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Java基础之for循环嵌套.docx](https://download.csdn.net/download/weixin_43171186/11991115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【C语言初学必看】一知半解的for循环嵌套for循环](https://blog.csdn.net/qq_68993495/article/details/124456024)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值