按钮多次点击致逐字打印文本叠加问题及代码优化求助
问题解决:多次点击按钮导致逐字打印文本叠加的修复方案
问题根源
每次点击按钮触发printText时,都会新建一个setInterval定时器。如果重复点击,之前的定时器没被清除,多个定时器会同时往目标元素里追加字符,直接导致文本叠加混乱。
解决思路
- 给每个元素绑定独立定时器标识:把定时器实例存在目标元素的
data属性中,每次调用printText前先清除该元素已有的定时器,确保同一时间只有一个定时器在运行 - 折叠面板时同步清定时器:收起面板时也要清除对应定时器,避免隐藏后定时器还在后台偷偷执行
- 简化定时器逻辑:优化字符拼接的判断条件,减少不必要的循环判断
优化后的代码
function printText(element) { // 先清除该元素已有的定时器,防止叠加 const existingTimer = element.data('printTimer'); if (existingTimer) { clearInterval(existingTimer); } element.text(''); const text = element.attr('data-text'); let counter = 0; const printTimer = setInterval(() => { if (counter < text.length) { // 直接基于当前文本追加字符,不用单独维护newText变量 element.text(prev => prev + text[counter]); counter++; } else { clearInterval(printTimer); // 定时器结束后移除元素上的标识 element.removeData('printTimer'); } }, 30); // 把定时器实例存到元素的data属性中 element.data('printTimer', printTimer); } accordingButtons.click(function(e) { const $target = $(this); const $targetBody = $target.attr('class') === 'polygon-but' ? $target.parent().parent().next() : $target.parent().next(); const toggleState = $target.attr('data-toggle'); if (toggleState === 'true') { // 折叠时清除定时器 const timer = $targetBody.data('printTimer'); if (timer) { clearInterval(timer); $targetBody.removeData('printTimer'); } $targetBody.animate({ opacity: 0.0, height: '0px', marginTop: '0px' }, 200); $target.attr('data-toggle', 'false'); } else if (toggleState === 'false') { $targetBody.animate({ opacity: 1, height: `+=${$targetBody.attr('data-number')}`, marginTop: '37px' }, 200); $target.attr('data-toggle', 'true'); printText($targetBody); } });
额外优化建议
- 用
$target.data('toggle')替代$target.attr('data-toggle'):jQuery的data()方法会自动缓存属性值,比直接操作DOM属性更高效 - 给按钮加防抖:如果担心用户疯狂快速点击,可以给点击事件加300ms的防抖逻辑,避免短时间内重复触发
- 边界值判断:可以提前判断
text是否为空,避免空文本时创建无效定时器
内容的提问来源于stack exchange,提问作者Holaves
相关产品推荐
相关产品推荐

