js事件重复绑定问题

先看一个简单的例子吧(为了方便,例子使用jQuery写的):

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button id='create'>点击生成新的button</button>
    <div id="button_box"></div>
</body>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>
    $(document).ready(function(){
        //创建节点函数:
        var createNew = function(){
            var new_button=document.createElement("button");
            new_button.innerHTML="点击触发事件";
            //为节点添加一个类,以便通过这个类为节点绑定事件
            $(new_button).addClass('event');

            $("#button_box").append(new_button);

            //为新创建的节点绑定事件
            $('.event').on('click', function(){
                console.log('clicked!');
            })
        };

        //生成节点按钮的点击事件
        $('#create').on('click', function(){
            createNew();
        });
    });
</script>
</html>

实际效果如下:

这里写图片描述

点击按钮生成四个按钮节点——–>

这里写图片描述

现在尝试着点击第1个新节点,想想控制台会输出什么——–>

这里写图片描述

很明显,每一个click事件会触发一次控制台输出,但是现在我点击第1个事件,控制台输出了四次。
这就是我今天想要说的js的事件会重复绑定的问题。


一、为什么会重复绑定?

首先我们先来分析一下,为什么会重复绑定。

我们看看我们的绑定事件是什么时候?对,是在新节点创建的时候被绑定到节点上的,而且是通过jQuery的选择器通过类名event 将所有新节点都绑定同样的事件。因此,我们每点击一次按钮生成一个新节点都会为class=event的节点绑定一次事件。而javascript是允许重复绑定事件的,所以问题就产生了。

当我创建了4次新节点时,第一个被创建的节点就被绑定了4次事件,所以产生了4次控制台的输出。

不要怀疑,为什么有这样的应用场景,要为这么多element绑定同样的事件。这种应用场景很普遍。比如一个类似于发帖子的页面,每一天回帖的样式和功能都是重复的,那么对于异步生成的新帖子绑定事件就会产生上面模拟的情况。


二、如何解决

通过$('.className').on('click', function(){ }) 这种方法绑定的事件,势必会有重复的情况。

1、放弃通过选择器$('.className') 来绑定事件:
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <button id='create'>点击生成新的button</button>
    <div id="button_box"></div>
</body>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>
    $(document).ready(function(){
        //创建节点函数:
        var createNew = function(){
            var new_button=document.createElement("button");
            new_button.innerHTML="点击触发事件";
            //为节点添加一个类,以便通过这个类为节点绑定事件
            $(new_button).addClass('event');

            $("#button_box").append(new_button);

            //为新创建的节点绑定事件
            //直接将事件绑定到新节点,跳过类选择器的重复问题
            $(new_button).on('click', function(){
                console.log('clicked!');
            })
        };

        //生成节点按钮的点击事件
        $('#create').on('click', function(){
            createNew();
        });
    });
</script>
</html>

这样每个element都唯一的绑定了一次事件,实际效果如下:

点击按钮生成四个按钮节点——–>

这里写图片描述

点击第1个新节点,控制台输出结果如下——–>

这里写图片描述

思考一下,这样做有一个不方便的地方:
如果我每次生成的新元素element有多个,我还能需要一个个地遍历然后单独为每一个添加。显然这样没有通过选择器$('.className') 绑定事件的优势更大。


2、通过选择器$('.className') 绑定事件前,先解绑:

解绑的方法很多,根据事件绑定的方法分别会有如下的对应关系:

  • jQ的事件解除绑定分别是:
绑定方法解绑方法
bindunbind
onoff
livedie
delegateundelegate


对于上面的例子,在绑定之前清除一次click事件:

//先清除一次事件
$('.event').off('click');
//为新创建的节点绑定事件
$('.event').on('click', function(){
     console.log('clicked!');
 })

这样执行出来的结果就和上面的解决方法一样。

这样就可以解决上面提到的问题了。同样再来深入的思考一下,绑定之前清除一次click事件又会带来什么问题?
如果之前元素已经绑定了另外一个click事件,那么现在的解绑就会造成之前事件的解绑,这样也是不符合期望的。


三、总结

事件重复绑定会带来的问题我这里就不多说了,这篇文章也只介绍了两种解决方法,各有优缺点,可以按照实际的情况去选择合适的方法。如果后面有更多地解决方法我会继续更新,当然如果有更好的解决方法,欢迎指教。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值