记一次,关于重复绑定点击事件的问题(已解决)

本文介绍了一种在JavaScript中使用回调函数实现弹窗确认提交功能的方法,并解决了因多次调用导致DOM元素重复绑定点击事件的问题。

一次中,想自己写一个弹窗提示确认提交的功能,在这个功能中使用回调函数的方式去实现对应模块功能。代码如下:
js代码:

function myConfirm(title,content,callback){
            $(".con-box").show(50);
            $(".con-title p").text(title);
            $(".con-content p").text(content);
            $(".btn").on('click',function(){
                if($(this).attr('data-id') == 'yes'){
                    if(typeof(callback) == 'function'){
                        callback();
                    }
                }
                $(".con-box").hide(50);
                $(".con-title p").text('这里显示提示标题');
                $(".con-content p").text('这里显示提示信息');
            });
        }

html代码:

<div class="con-box">
        <div class="con-title">
            <p class="title-info">这里显示提示标题</p>
        </div>
        <div class="con-content">
            <p class="content-info">这里显示提示信息</p>
        </div>
        <div class="con-btn">
            <div class="btn-yes">
                <p class="yes-txt btn" data-id="yes">确认</p>
            </div>
            <div class="btn-no">
                <p class="no-txt btn" data-id="no">取消</p>
            </div>
        </div>
    </div>

css代码:

.con-box{
            position: fixed;
            top: 50%;
            left: 50%;
            width:auto;
            height:auto;
            transform:translate(-50%,-50%);
            background: #FFFFFF;
            border-radius:3px;
            box-shadow:1px 1px 3px;
            z-index:10;
            opacity:1;
            text-align:center;
            line-height:30px;
            display: none;
        }
        .con-box .con-title{
            padding:5px 3%;
            width:94%;
            display: table;
            border-bottom:1px solid #dddddd;
        }
        .con-box .con-content{
            padding:15px 25px;
            width:auto;
            border-bottom:1px solid #dddddd;
        }
        .con-box .con-btn{
            display: table;
            margin:0 auto;
            padding:5px 10px;
            width:90%;
        }
        .con-box .con-btn .btn-yes,.con-box .con-btn .btn-no{
            display: table;
            margin:5%;
            float: left;
            width:40%;
            height:30px;
            border-radius:3px;
            box-shadow:1px 1px 3px;
        }
        .con-box .con-btn .btn-no{
            background:#ff0000;
        }
        .con-box .con-btn .btn-yes{
            background:#007DDB;
        }
        .con-box p{
            display: table-cell;
            vertical-align: middle;
        }
        .con-box .con-btn p{
            color:#FFFFFF;
        }

然后在页面我写了两个按钮,一个是检测验证码是否正确(使用了ajax实现异步检测),另一个是弹出提示信息,但在执行过程中,发现了一个问题,就是当点击了其中一个按钮后,再点击另一个按钮时,系统竟然会执行上一次点击按钮的回调函数 : ( ,
页面如下:
页面
当我点了验证后显示:
这里写图片描述

点击确认执行回调函数ajax验证,弹出提示结果:
这里写图片描述
这时当我又点击另一个按钮时,会发生执行了这一次回调函数后,会再执行上一次的回调函数:
本来这个按钮是这样提示的:
这里写图片描述

实际上提示这个后,会再次弹出:
这里写图片描述

后来发现,这是因为$(’.btn’)这个DOM元素在调用函数时,会重新绑定一次点击事件,多次调用,就变成绑定了多次点击事件,造成之后每一次点击,事实上是执行了多个点击绑定的函数,因此在绑定点击事件前,先解绑一下就可以了:


```javascript
$(".btn").unbind('click').on('click',function(){
                if($(this).attr('data-id') == 'yes'){
                    if(typeof(callback) == 'function'){
                        callback();
                    }
                }
                $(".con-box").hide(50);
                $(".con-title p").text('这里显示提示标题');
                $(".con-content p").text('这里显示提示信息');
            });
<think>好的,我现在需要解决用户的问题:在Vue3和Element-Plus中,如何实现点击两次后触发一次单击事件。首先,用户之前的问题是关于双击触发两次单击的问题,现在反过来,用户希望点击两次后才触发一次单击事件。这可能是一个特定的需求,比如防止误操作,或者需要用户确认点击动作。 首先,我需要理解用户的需求。用户可能希望用户在快速点击两次之后,才执行某个操作,而不是第一次点击就触发。这和之前的双击问题相反,之前是避免双击触发两次单击,现在是要利用两次单击来触发一次事件。 接下来,我需要考虑如何实现这个逻辑。可能的思路是录点击次数,设置一个间间隔,如果在规定间内点击了两次,则执行一次单击事件。如果在间间隔内没有达到两次点击,则不执行或者重置计数器。 首先,我需要一个计数器来跟踪点击次数。每次点击,计数器加一。然后设置一个定器,如果在设定的间(比如300ms)内再次点击,计数器再次加一。当计数器达到2,触发事件,并重置计数器。如果在间间隔内没有第二次点击,则重置计数器。 需要注意的是,每次点击后都要重置定器,否则多次点击可能会导致多个定器同运行。例如,用户点击一次,定器启动,如果在定器结束前再次点击,应该取消之前的定器,重新开始计,同检查是否满足两次点击的条件。 然后,我需要考虑如何在Vue3中实现这个逻辑。可以使用ref来保存计数器和定器的引用。在点击事件的处理函数中,增加计数器,并管理定器的设置和清除。 可能的代码结构如下: 在模板中,绑定点击事件到方法: ```vue <el-button @click="handleMultiClick">点击两次触发</el-button> ``` 在脚本中,定义处理函数: ```javascript import { ref } from 'vue'; const clickCount = ref(0); let timer = null; const delay = 300; // 设置间间隔 const handleMultiClick = () => { clickCount.value += 1; if (timer) { clearTimeout(timer); } timer = setTimeout(() => { if (clickCount.value === 2) { // 执行单击事件 console.log('触发单击事件'); } // 重置计数器 clickCount.value = 0; }, delay); }; ``` 这样,每次点击会先清除之前的定器,然后重新设置。如果在300ms内点击两次,计数器会累加到2,触发事件后重置。否则,定器结束后重置计数器。 但这里有个问题,用户可能需要的是两次点击后触发一次单击事件,而不是累积点击次数。可能需要更精确的判断,比如两次点击之间的间间隔不超过设定值,而不是总的点击次数。 或者,用户可能希望两次独立的点击,中间可能有间隔,但希望两次后触发一次。不过这种情况比较少见,通常需要的是双击或者在短间内连续点击。 另外,需要考虑用户是否希望每次两次点击后都触发一次,还是仅在两次点击后触发一次,之后重新开始计数。根据代码逻辑,每次两次点击在间间隔内都会触发,之后计数器重置,可以重复触发。 但用户的问题描述是“实现点击两次后在方法中触发一次单击事件”,可能意味着无论两次点击的间间隔如何,都要在第二次点击触发一次。这种情况下,可能需要不同的处理方式,比如每次点击都间,判断两次点击的间差是否在允许范围内。 不过通常,这种需求还是基于间间隔内的两次点击,否则用户可能无意中多次点击,导致意外触发。 另外,用户之前的问题是关于Element-Plus的双击事件,现在的问题可能仍然是在Element-Plus组件中使用,比如按钮或表格行。需要确保事件绑定正确,没有冲突。 比如,在Element-Plus的按钮上,直接使用@click事件,然后在处理函数中管理点击次数和定器。或者可能需要自定义指令来封装逻辑,方便复用。 此外,还需要考虑事件传递和事件对象的问题,比如是否需要阻止默认行为或事件冒泡,但根据问题描述,暂不需要处理这些。 总结步骤: 1. 创建一个计数器,录点击次数。 2. 每次点击,增加计数器,并启动/重置定器。 3. 定器的作用是在间间隔后检查计数器是否为2,如果是,则触发事件,并重置计数器。 4. 如果在定器触发前有第二次点击,计数器增加到2,定器被清除并重新设置,此在第二次点击后,定器再次启动,但如果在间间隔内没有第三次点击,定器触发计数器是2,执行事件。 不过,这样可能在两次点击后,定器在间间隔结束触发事件。而用户可能希望在第二次点击立即触发,而不是等待定器结束。例如,用户点击两次,第二次点击立即触发事件,而不是等待延迟间。这需要调整逻辑。 可能的另一种方法是,在每次点击间戳,检查与前一次点击的间差是否小于阈值。如果是,则触发事件,并重置录。否则,更新最后一次点击的间。 例如: ```javascript let lastClickTime = 0; const delay = 300; const handleMultiClick = () => { const currentTime = new Date().getTime(); if (currentTime - lastClickTime < delay) { // 两次点击在间间隔内,触发事件 console.log('触发单击事件'); lastClickTime = 0; // 重置,避免连续三次点击触发两次 } else { // 更新最后一次点击间 lastClickTime = currentTime; } }; ``` 这种方法在第二次点击立即判断与前一次间差,如果符合条件则触发。但这样可能在快速点击多次多次触发,比如三次点击可能在第二和第三次之间也满足条件,导致触发两次。需要根据需求调整,比如触发后重置间戳为0,这样第三次点击会被视为第一次,直到再次有两次点击在间隔内。 不过用户的需求是点击两次后触发一次,所以可能更倾向于在第二次点击立即触发,而不是等待定器。因此,这种方法可能更合适。 但需要测试不同情况下的行为,比如两次点击间隔超过delay,第三次点击如何处理等。 现在需要结合用户的具体需求,如果用户希望无论两次点击的间隔如何,只要累计点击两次就触发一次,那么可能需要不同的逻辑,比如使用计数器,在每次点击增加,当计数器达到2触发,然后重置。但这可能不符合常规需求,因为用户可能在较长间内点击多次,导致多次触发。 综上,用户的需求可能更倾向于在短间内连续点击两次后触发一次事件,因此使用间间隔判断的方法更为合适。 回到最初的解决方案,使用定器和计数器的方法可能在第二次点击后需要等待定器结束才能触发事件,这可能不符合用户的预期,因为用户希望第二次点击后立即触发。因此,需要调整逻辑,使得在第二次点击立即触发,而不是等待定器。 可能的调整方法是:在每次点击,如果是第一次点击,启动定器;如果是第二次点击且在定器未超的情况下,立即触发事件,并清除定器,重置计数器。 代码示例: ```javascript let clickCount = 0; let timer = null; const delay = 300; const handleMultiClick = () => { clickCount += 1; if (clickCount === 1) { timer = setTimeout(() => { // 单次点击,未达到两次,不触发 clickCount = 0; }, delay); } else if (clickCount === 2) { clearTimeout(timer); // 触发事件 console.log('触发单击事件'); clickCount = 0; } }; ``` 这样,当用户第一次点击,启动定器,如果在delay间内再次点击,则clickCount变为2,清除定器,触发事件,并重置计数器。如果在delay间内没有第二次点击,定器将计数器重置为0。 这种方法在第二次点击立即触发事件,而不是等待定器结束,这样更符合用户的预期,即两次点击后立即触发一次事件。 现在,需要将这个逻辑应用到Vue3中,可能需要使用响应式变量来跟踪clickCount,但由于定器和计数器可能不需要响应式,可以使用普通变量,除非需要在模板中显示点击次数。 在Vue3的setup语法中: ```vue <script setup> let clickCount = 0; let timer = null; const delay = 300; const handleMultiClick = () => { clickCount += 1; if (clickCount === 1) { timer = setTimeout(() => { clickCount = 0; }, delay); } else if (clickCount === 2) { clearTimeout(timer); // 触发单击事件 console.log('触发单击事件'); clickCount = 0; } }; </script> ``` 然后在模板中绑定: ```vue <el-button @click="handleMultiClick">双击触发单击</el-button> ``` 这样,当用户快速点击两次按钮,第二次点击会立即触发事件。如果在delay间之后点击第二次,则第一次点击的定器已经将计数器重置,第二次点击被视为第一次点击,启动新的定器,不会触发事件。 这种方法满足了用户的需求:在短间内点击两次后触发一次单击事件。 另外,需要考虑事件处理函数中的this指向问题,但在Vue3的setup语法中使用箭头函数或普通函数不会有问题,因为setup中的函数是局部作用域。 最后,可能需要将delay间调整为用户认为合适的间隔,通常300ms是一个合理的双击间隔间,但可以根据实际需求调整。</think>在 Vue3 中,可以通过 **计数器 + 定器** 实现点击两次后触发一次单击事件的逻辑。以下是具体实现方法: --- ### 实现思路 1. **计数器录点击次数**:第一次点击启动定器,第二次点击若在间间隔内,则触发目标逻辑。 2. **定器重置状态**:若超过间间隔未再次点击,重置计数器。 --- ### 代码实现 ```vue <template> <el-button @click="handleDoubleClickTrigger"> 点击两次后触发一次 </el-button> </template> <script setup> let clickCount = 0; // 录点击次数 let timer = null; // 定器 const delay = 300; // 间间隔(单位:ms) const handleDoubleClickTrigger = () => { clickCount += 1; // 点击次数+1 if (clickCount === 1) { // 第一次点击:启动定器,超后重置计数器 timer = setTimeout(() => { clickCount = 0; }, delay); } else if (clickCount === 2) { // 第二次点击(且在间间隔内):触发目标逻辑 clearTimeout(timer); // 清除定器 clickCount = 0; // 重置计数器 // 在这里执行单击事件逻辑 console.log("触发单击事件"); // yourSingleClickMethod(); } }; </script> ``` --- ### 核心逻辑解析 1. **第一次点击**:录点击次数为 `1`,并启动一个 `delay` 毫秒的定器。 2. **第二次点击**: - 若在 `delay` 间内触发,清除定器,执行目标逻辑,重置计数器。 - 若超过 `delay` 间,定器会自动重置计数器,第二次点击被视为“第一次点击”。 --- ### 优化扩展 #### 封装成自定义指令(全局复用) ```javascript // main.js app.directive('double-trigger', { mounted(el, binding) { let clickCount = 0; let timer = null; const delay = 300; el.addEventListener('click', () => { clickCount += 1; if (clickCount === 1) { timer = setTimeout(() => clickCount = 0, delay); } else if (clickCount === 2) { clearTimeout(timer); clickCount = 0; binding.value(); // 执行传入的回调函数 } }); } }); // 使用 <el-button v-double-trigger="yourMethod">按钮</el-button> ``` -- #### 在 Element-Plus 组件中的应用(如表格行) ```vue <el-table @row-click="handleRowDoubleTrigger"> <!-- 表格内容 --> </el-table> <script setup> const handleRowDoubleTrigger = (row) => { let clickCount = 0; let timer = null; const delay = 300; return () => { clickCount += 1; if (clickCount === 1) { timer = setTimeout(() => clickCount = 0, delay); } else if (clickCount === 2) { clearTimeout(timer); clickCount = 0; console.log("行单击事件触发", row); } }; }; </script> ``` -- ### 注意事项 1. **间间隔(`delay`)**:推荐 `200~300ms`,可根据用户体验调整。 2. **防抖处理**:避免快速多次点击导致逻辑混乱。 3. **兼容性**:适用于按钮、表格行、自定义元素等任何需要此逻辑的场景。 通过这种方式,可以精准控制“点击两次触发一次”的行为,适用于需要用户确认操作的场景(如删除确认)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值