ExtJS 3.4按钮点击事件多次触发问题求助
问题根源分析
兄弟,你遇到的这个“点击次数逐次增加、计算结果异常”的问题,本质是重复绑定事件监听器导致的:
每次调用openCustDeposit打开窗口B时,你都会执行dep.grid.custDepositPostBtn.on('click', function(...) {...}),但窗口B是通过closeAction:'hide'隐藏复用的,并没有被销毁。这就导致每打开一次窗口,按钮上就多挂一个点击事件,点击时自然会触发N次(N等于打开次数),算术运算重复执行,结果当然会乱掉!
解决方案
下面给你几个针对性的修复方案,按推荐程度排序:
方案1:将事件绑定移到窗口初始化逻辑中(最优)
既然窗口B是只创建一次、复用多次的,那事件绑定只需要在窗口第一次创建时执行一次就行。把绑定代码移到if (!windep)的分支里:
function openCustDeposit(idCustomer) { require(['view/Deposit'], function (dep) { var windep= Ext.getCmp('windep'); if (!windep) { windep= new Ext.Window({ ... items : [dep.initObj], plain : true, closable: true, closeAction :'hide', ... listeners:{ show:function() { this.loadMask = new Ext.LoadMask(this.body, { msg:'Loading. Please wait...' }); }, destroy:function(){ if(this.mask)delete this.mask; } } }); // 👉 只在窗口第一次创建时绑定事件,避免重复 dep.grid.custDepositPostBtn.on('click', function(obj,evt) { try { var str_idCrdtMemo='', str_CRApply='', sumCRApply=0; var objGrid = grid; var selRec = objGrid.selModel.getSelected(); .... selRec.set('CustDeposit', sumCRApply); selRec.set('idPostCheck', str_idCrdtMemo.substr(0,str_idCrdtMemo.length-1)); selRec.set('CustDeposit2', str_CRApply.substr(0,str_CRApply.length-1)); .... closeWin(arCustDeposit.grid); // window close } catch (e) { Ext.MessageBox.alert('Error', e); } finally { .... } }); } else { .... } ... windep.show(); ... dep.store.load(); }); }
方案2:绑定前先解绑已有监听器
如果因为业务原因,必须每次打开窗口都绑定事件,那绑定前先移除按钮上的已有监听器:
先把事件处理函数抽成独立函数,方便后续精准解绑:
// 抽离独立的事件处理函数,方便解绑 function handleDepositPost(obj, evt) { try { var str_idCrdtMemo='', str_CRApply='', sumCRApply=0; var objGrid = grid; var selRec = objGrid.selModel.getSelected(); .... selRec.set('CustDeposit', sumCRApply); selRec.set('idPostCheck', str_idCrdtMemo.substr(0,str_idCrdtMemo.length-1)); selRec.set('CustDeposit2', str_CRApply.substr(0,str_CRApply.length-1)); .... closeWin(arCustDeposit.grid); // window close } catch (e) { Ext.MessageBox.alert('Error', e); } finally { .... } } function openCustDeposit(idCustomer) { require(['view/Deposit'], function (dep) { var windep= Ext.getCmp('windep'); if (!windep) { windep= new Ext.Window({ ... }); } else { .... } ... windep.show(); ... dep.store.load(); // 👉 先解绑再绑定,彻底避免重复 dep.grid.custDepositPostBtn.un('click', handleDepositPost); dep.grid.custDepositPostBtn.on('click', handleDepositPost); }); }
方案3:使用once绑定单次事件(适合特定场景)
如果每次打开窗口B后,只需要点击一次保存按钮,之后不需要再触发这个事件,可以用once代替on,这样事件只会触发一次,触发后自动解绑:
dep.grid.custDepositPostBtn.once('click', function(obj,evt) { // 原事件逻辑不变 });
额外调试小技巧
后续遇到类似问题时,可以用dep.grid.custDepositPostBtn.hasListener('click')或者查看浏览器开发者工具的元素事件绑定列表,快速确认是否存在重复绑定的情况。
内容的提问来源于stack exchange,提问作者Min Lee
相关产品推荐
相关产品推荐

