您的位置:首页 > Web前端 > JavaScript

js事件重复绑定问题

2015-08-13 12:24 666 查看
先看一个简单的例子吧(为了方便,例子使用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事件,那么现在的解绑就会造成之前事件的解绑,这样也是不符合期望的。

三、总结

事件重复绑定会带来的问题我这里就不多说了,这篇文章也只介绍了两种解决方法,各有优缺点,可以按照实际的情况去选择合适的方法。如果后面有更多地解决方法我会继续更新,当然如果有更好的解决方法,欢迎指教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息