一个事件冒泡和事件叠加的问题!
事情的原委是项目中使用了模态框,由于新增和编辑的样式一样,所以我让两个操作共用一个模态框,而且共用一个提交按钮。但是两个操作放到两个不同的后台地址处理,那么问题来了,我在add和edit时,分别为submit按钮绑定不同的单击事件。我的理想是,点击了add后,submit的单击事件提交到后台的insert,点击edit后,submit的单击事件提交到后台的update。但是实际测试时,发现了一个致命的问题,就是页面是异步加载的,点击过submit后,会随着点击次数的增加,执行多次点击事件。
单独模拟了一下事件的原型:
<div class="out">
<div class="in"></div>
</div>
$('.out').click(function(){
var n = parseInt(Math.random() * 1000);
console.log(n);
$('.in').click(function(){
console.log(n);
});
});
只模拟了一种绑定情况,就是只有点击了外部div,才为内部div绑定一个单击事件的操作。
然后,开始我们刺激的测试了。
第一次点击in的div,打印349;
第二次点击,打印349,752;
第三次点击,打印349,752,551;
第四次点击,打印349,752,551,219;
第五次点击,………..
和项目问题符合了,然后开始查找原因,发现了两个原因:1是事件的冒泡;2是事件的叠加。
那么就可以解释上面的结果了,in的单击事件,只有在out点击了才会为其绑定。第一次点击时,因为还没有为in绑定单击事件,所以他会寻找它的父级以及更父级的事件,直到执行或返回false,这时他找到了父级的out的单击事件,于是打印了349,并为in绑定了一个打印349的单击事件;第二次点击时,in本身有单击事件,于是打印349,但是没有阻止事件冒泡,又执行了父级out的单击事件,并打印出752,并又一次为in绑定了一个打印752的事件,于是第二次的打印结果为349,752;第三次点击时,in本身有两个点击事件,打印349,打印752,于是先执行自己的单击事件,又冒泡执行父级的单击事件,打印了551,而out又为in绑定了一个打印551的事件;第四次点击时,同样的逻辑……
问题简单点说,就是点击in会执行out的冒泡事件,而out的冒泡事件又为in叠加绑定了单击事件,所以随着单击次数的增加,会打印更多的值。很明显,我们是不想要in的叠加事件的,但是又想要父级本身的点击事件,那么怎么做呢?需要每次执行in的事件时,先清除自身的绑定事件,再重新绑定新事件。改进后如下:
$('.out').click(function(){
var n = parseInt(Math.random() * 1000);
console.log(n);
$('.in').unbind('click');
$('.in').click(function(){
console.log(n);
});
});
第一次点击,打印458;
第二次点击,打印458,741;
第三次点击,打印741,965;
第四次点击,打印965,826;
OK,达到我们想要的结果了,随着父级事件的不同,内部事件改变。但是这种重复绑定事件,删除事件,效率太不好。因此最好的方法,还是定义一个in的单击事件,通过参数判断是提交到哪个后台更好。