使用TypeItJS开发游戏intro时storyAdvance()执行两次致stage重复累加问题
嘿,我之前用TypeItJS做交互叙事类项目时也踩过类似的重复触发坑,太懂这种明明逻辑没问题但数值莫名翻倍的抓狂感了😅。针对你遇到的第二阶段storyStage被累加两次、storyAdvance()执行两次的问题,结合你的猜想和实际踩坑经验,给你几个具体的排查方向和解决思路:
优先验证事件解绑猜想
你怀疑的#story元素未解绑事件确实是高概率原因。如果每次进入新故事阶段时,都重新给#story绑定了触发storyAdvance()的事件(比如点击、完成回调),但没有移除之前的绑定,就会导致同一事件触发一次却执行多次函数。
解决思路:- 在绑定新事件前,先主动移除旧绑定:
const storyEl = document.querySelector('#story'); // 先解绑再绑定 storyEl.removeEventListener('click', storyAdvance); storyEl.addEventListener('click', storyAdvance); - 或者改用事件委托,在父级元素上只绑定一次事件,通过判断目标元素来触发逻辑,避免重复绑定的问题。
- 在绑定新事件前,先主动移除旧绑定:
排查TypeItJS实例的回调重复触发
TypeIt的完成回调(比如afterComplete)如果配置不当,可能会因为多实例创建、循环设置等原因重复触发。检查你初始化第二阶段TypeIt的代码:- 是否在进入第二阶段时重复创建了TypeIt实例?
- 回调函数里是否不小心嵌套调用了
storyAdvance()?
举个例子,如果你的代码类似这样,要确保实例只创建一次:// 错误示例:可能多次执行这段代码创建多实例 new TypeIt('#story', { afterComplete: () => { storyAdvance(); } }).type('第二阶段剧情文本').go();
检查页面中是否存在多个
#story元素
有时候动态渲染DOM时,可能会意外生成多个id为story的元素(id本应唯一),导致事件绑定到了所有匹配节点上,触发时就会多次执行storyAdvance()。你可以在浏览器控制台输入document.querySelectorAll('#story'),看看返回的节点数量,如果大于1,就需要修正DOM渲染逻辑,保证id唯一。添加日志精准定位触发源
最直接的方式是给storyAdvance()加日志,明确每次触发的时间和触发元素:function storyAdvance() { console.log('storyAdvance触发时间:', new Date().getTime(), '触发元素:', event.target); // 你的原有逻辑代码 }通过控制台日志,你能清楚看到是同一元素被多次触发,还是不同元素触发,也能结合时间戳判断触发的上下文,快速缩小根因范围。
内容的提问来源于stack exchange,提问作者Ryan Schaefer

