如何避免下载按钮因重复绑定事件监听器多次触发
解决多次搜索后下载按钮重复触发事件的问题
问题根源
每次点击搜索按钮执行readData时,都会给downloadBtn新增一个点击事件监听器,多次搜索后,点击下载会触发所有历史绑定的下载逻辑,导致重复下载。
解决方案
方案一:每次添加新监听器前移除旧监听器
通过保存当前回调函数的引用,在绑定新监听器前先移除旧的,确保始终只有一个监听器生效:
// 保存当前下载回调的引用 let currentDownloadCallback = null; searchBtn.addEventListener('click', getTransactionDetails); const readData = async(data) => { // ... 原有数据处理代码 ... api.call('GetAddresses', { coordinates: coordinates }, async addresses => { // ... 原有循环处理代码 ... csvToTable(csvData.join('\n'), transactionIdsAtIndex); // 移除之前的监听器(如果存在) if (currentDownloadCallback) { downloadBtn.removeEventListener('click', currentDownloadCallback); } // 创建新的回调并保存引用 currentDownloadCallback = () => downloadFilesAsZip(data, csvData.join('\n'), count); // 绑定新的监听器 downloadBtn.addEventListener('click', currentDownloadCallback); }, err => console.log(err)); }
方案二:将下载监听器移到外部,用变量保存最新数据
这种方式更简洁,只给下载按钮绑定一次监听器,通过变量保存每次搜索后的最新数据,点击下载时直接使用最新数据:
// 定义变量保存最新的下载所需数据 let latestDownloadInfo = null; // 下载按钮只绑定一次监听器 downloadBtn.addEventListener('click', () => { if (latestDownloadInfo) { const { data, csvStr, count } = latestDownloadInfo; downloadFilesAsZip(data, csvStr, count); } }); searchBtn.addEventListener('click', getTransactionDetails); const readData = async(data) => { // ... 原有数据处理代码 ... api.call('GetAddresses', { coordinates: coordinates }, async addresses => { // ... 原有循环处理代码 ... const csvStr = csvData.join('\n'); csvToTable(csvStr, transactionIdsAtIndex); // 更新最新的下载数据 latestDownloadInfo = { data, csvStr, count }; }, err => console.log(err)); }
为什么之前的尝试无效?
- 使用
{once: true}会让搜索按钮只能触发一次点击事件,直接限制了多次搜索的需求,不符合场景。 - 克隆按钮的方式如果没有正确替换原有按钮或清理旧监听器,依然会残留历史绑定的事件,无法从根本上解决问题。
内容的提问来源于stack exchange,提问作者mrplayingame
相关产品推荐
相关产品推荐

