JS按钮绑定EventListener点击不执行且控制台无报错
问题原因
点击Swap无响应、控制台无报错的核心问题是事件绑定时机早于动态元素的渲染时机:
- 页面初始加载时,class为
js-token-balances的tbody标签内部为空,不存在任何带js-swap类的Swap按钮 - 你写的事件绑定for循环在页面初始化阶段同步执行,此时执行
querySelectorAll(".js-swap")只能拿到空的节点集合,没有给任何按钮绑定上点击处理函数 - Swap按钮是
getBalances()异步拉取用户代币余额完成后,才通过innerHTML动态插入到DOM中的。这些后生成的按钮从未绑定过initSwapForm事件,点击自然不会触发对应逻辑,也不会抛出任何错误。
修复方法
二选一即可:
方法一:动态渲染完成后再绑定事件
把事件绑定逻辑移到getBalances()函数内部,等DOM插入完成后再查找按钮绑定事件,修改后的getBalances代码:
async function getBalances () { const balances = await Moralis.Web3API.account.getTokenBalances(); console.log(balances); $tokenBalanceTbody.innerHTML=balances.map((token,index)=>` <tr> <td>${index +1}</td> <td>${token.symbol}</td> <td>${tokenValue(token.balance, token.decimals)}</td> <td> <button class="js-swap btn btn-info" data-address="${token.token_address}" data-symbol="${token.symbol}" data-decimals="${token.decimals}" data-max="${tokenValue(token.balance, token.decimals)}" > Swap </button> </td> </tr> `).join(""); // DOM渲染完成后再绑定事件 for (let $btn of $tokenBalanceTbody.querySelectorAll(".js-swap")){ $btn.addEventListener("click", initSwapForm) } }
注意:把原来写在getBalances函数外部的for循环事件绑定代码删掉,避免后续重复绑定。
方法二:事件委托(推荐)
直接把事件绑定到页面加载时就已经存在的父元素$tokenBalanceTbody上,利用事件冒泡机制匹配触发的子元素,不管后续动态插入多少个按钮都能自动响应,不需要反复绑定。把原来的for循环绑定代码替换成下面这段即可:
$tokenBalanceTbody.addEventListener("click", (e) => { if (e.target.matches(".js-swap")) { initSwapForm(e); } })
这种方式不需要关心元素的渲染时机,后续新增同类操作按钮也不需要额外写绑定逻辑,维护成本更低。
修改完成后点击Swap按钮,即可正常执行代币信息填充、解除金额输入框禁用状态、启用提交/取消按钮、清空报价容器的逻辑。
内容的提问来源于stack exchange,提问作者Petar Todorov
相关产品推荐
相关产品推荐

