JS动态添加元素和绑定事件 导致程序重复执行
序
本文主要给大家讲讲前段时间遇到的Bug。这个bug是关于jquery的on方法绑定交互事件。像$ ('# point ')这样的代码。打开('点击','。read-more ',function () {})导致程序重复执行。很多人在文章中写了这件事,还说要用off方法解决问题,但是没有指出问题
话不多说,我每天看到的代码:
第一种:
$(文档)。on ('click ',函数(e) {consol.log ('jquery事件绑定')});第二种类型:
document . addevent listener(' click ',函数(e) {consol.log('本机事件绑定')});第三种:
var ID=set interval(function(){ console . log('定时器循环事件绑定')},1000);以上代码,相信很多盟友,每天都会写。看似简单的事件绑定往往能给我们带来意想不到的效果,尤其是在这个SPA中,当AJAX页面部分刷新如此流行的时候。
那么什么是导致程序重复执行的事件绑定呢?看来这件事并不是那么简单就能说清楚的。让我们用测试代码来解释一下。您可以在本地复制并亲自尝试:
!doctype html head metharset=' utf-8 ' title/title/headsdybuttonclass=' add _ but ' click/button div id=' point ' fdfsdf/div script src=' http :3359 cdn . bootscs.com/jquery/1 . 8 . 3/jquery . js '/script script var count=1;var example={ getdata : function(){ var data={ content : ' df ' count,href : ' ' };this.renderData(数据);},render data : function(data){ document . getelementbyid(' point ')。innerhtml=' div这是一个' data.content '单击此处a class=' read-more ' href=' javasript 3360;rel=' external no follow ' rel=' external no follow '查看更多/a/div;$ ('# point ')。打开('点击','。read-more ',function () {alert('事故点');})/* SetInterval(function(){ console . log(' fdfdfdfg ');},2000);*//*使用冒泡来绑定事件,这类似于Jquery的on-binding事件*//* document . queryselector(' body ')。addeventlistener ('click '),函数(e){ if(e . target . class list . contains(' read-more ')){ alert('意外发生。} })*/} } ;document.querySelector('。add _ but’)。addEventListener('click '),函数(e){ example . getdata();e . stopperminactiptepropagation();});/script/body/html以上是我写的一个测试代码,为了把这件事解释清楚,所以我可以复制过来试试。当我们点击页面上的按钮触发函数example.getData()的调用时,在成功模拟ajax获取数据后,我们会根据本地情况,用页面中的元素类名点来刷新内容,并在加载这个内容时,将一个事件绑定到read-more A标签上,这样就出现了想要的效果。第一次加载元素时,页面正常,“事故发生点”弹出一次。当第二次刷新被触发时,你会发现它。
OMG,这个节目怎么了?我知道每次绑定事件之前,前面绑定的元素都会被删除。为什么,被删除的身体感觉还在动?嗯,以上是我遇到这种情况的第一个感叹。
最后问了问身边的大神,突然意识到绑定一直都在,只不过这个绑定保存在一个叫事件队列的地方。他不在循环执行的主线里,画了一张需要默契才能理解的画,所以他勉强看了一眼。
事件队列
恢复真相
其实上面的代码是专门为了测试而写的。除了计时器,其他两个点击事件都是正常写入,不会重复执行。正常代码:
jquery事件直接绑定的编写;$ ('#点。阅读-更多')。on ('click '),function () {alert('事故点');})//编写本机JS事件的直接绑定;Document.queryselector('。阅读-更多')。addeventlistener ('click '),函数(e) {alert('事故发生点');})你看到区别了吗?事实上,事件不是冒泡委托事件,而是直接绑定到添加的元素。因此,Dom事件是合理的。如果元素是动态添加的,它将动态绑定到此事件。元素被删除后,绑定到它的相应事件实际上会从事件绑定队列中删除,而不是像上面那样测试代码,这给人的印象是元素被移除后,绑定的事件仍然在内存中。但是,请记住,这是一个误解。上面测试的代码之所以给人这种错觉,是因为我们没有将事件绑定到动态添加的元素上,而是只使用了事件委托的形式。事实上,事件绑定到#point元素,该元素始终存在。我们使用事件冒泡让程序知道我们点击了动态添加的链接元素。在测试中,原生js被专门用来重现这个事件委托。事实上,jquery的on绑定事件的原理基本相同。
Document.queryselector ('body ')。addeventlistener ('click '),函数(e){ if(e . target . class list . contains(' read-more ')){ alert('事故点');}})那些消除bug的方法
计时器
这是最容易犯的错误,当然也是最容易解决的错误,因为定时器设置好之后,会返回一个数值,应该是事件队列的定时器中的一个数字,类似于9527;步骤是设置一个全局变量来保存返回值id。每次设置定时器时,设置的定时器首先由id清零
clearInterval(intervalId);//粗略书写intervalid clear interval(intervalid);//严格写入有效=set interval(function(){ console . log(' fdfdfdfg ');},2000);Dom事件
事实上,正如我们上面所说,最直接的方式是使用直接绑定,而不是事件委托;如果您真的想将事件与事件委托绑定,那么它就是解除绑定。jquery中提供了Unbind函数来解除事件的绑定,但是在jquery 1.8版本之后,不建议使用这个方法,但是建议使用off方法。例如,在上面的事件委托方式中,要解除绑定,语句$ ('# point ')。关闭('点击',')。可以使用“更多阅读”)。
有缺陷的解决方案,添加标志
很容易理解,第一次绑定之后,设置了flag,下一次执行绑定的时候,程序就会知道这个节点上已经有绑定了,所以就不需要再添加了。具体操作如下:
var标志=falsevar example={ getdata : function(){ var data={ content : ' df ' count,href : ' ' };this.renderData(数据);},render data : function(data){ document . getelementbyid(' point ')。innerhtml=' div这是一个' data.content '单击此处a class=' read-more ' href=' javasript 3360;rel=' external no follow ' rel=' external no follow '查看更多/a/div;标记$ ('# point ')。打开('点击','。read-more ',function () {alert('事故点' data . content);});flag=true} };逻辑上看起来没有问题,但仔细观察发现有问题。当我们第二次和第三次刷新时,弹出框的内容与第一次模拟刷新后点击后弹出的内容相同,即“事故发生点df1”,而不是随着内容增加。为什么呢?感觉事件队列中的回调函数被单独保存了,数据被深度复制而不是引用。有点难以理解,也不知道为什么。如果有人能说清楚,请告诉我。
最后,其实在编写一些程序的时候,很少会发生事件绑定,导致程序的重复执行。它通常发生在我们编写插件的时候,插件需要适应各种调用环境,所以防止插件内部事件的重复绑定是非常重要的。
摘要
以上就是本文的全部内容。希望本文的内容对大家的学习或工作有一定的参考价值。有问题可以留言交流。谢谢你的支持。
版权声明:JS动态添加元素和绑定事件 导致程序重复执行是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。