Tampermonkey脚本DOM更新后textContent仍返回旧值问题
异常原因拆解
1. 控制台输出存在天然误导
浏览器控制台打印DOM节点引用时,不会生成打印瞬间的静态内容快照,只会保存一个指向实时DOM的指针。控制台渲染这条日志的预览内容时,会在你查看日志的时间点实时拉取DOM的当前状态,这和同一段代码里同步执行的textContent读取(在代码运行瞬间就完成值的获取、输出)存在天然时间差。
你看到控制台里元素预览显示最新的12-7,是你后续打开控制台时DOM已经更新完成的状态,但同一时间输出的6-3是代码运行瞬间同步读取到的旧值,两者根本不是同一时间点的内容,不是textContent读取逻辑本身失效。
2. 脚本本身存在执行逻辑bug
- 点击触发的题目更新是异步流程:调用
click()方法后,点击事件的回调、题目渲染、DOM更新操作都会被排到当前同步执行栈之后,脚本在点击操作完成后立刻同步读取currgamename的文本,根本等不到新题目渲染完成,自然拿到上一轮的旧题目值。 - 脚本存在DOM篡改操作:代码中写入的
document.getElementById('currgamename').innerHTML = 'hello',直接覆盖了题目元素的原有内容,会干扰页面本身的题目更新逻辑,进一步导致读取到的内容和页面实际题目错位。 - 固定间隔的盲等逻辑不可靠:1秒的固定轮询没有校验题目是否真的更新完成,很容易在页面还在加载题目的阶段就读取内容,拿到旧值。
首次运行正常是因为页面初始加载的题目已经在DOM中存在,第一轮读取能拿到正确值;从第二轮开始,点击触发的新题目加载是异步流程,固定间隔的读取永远赶不上DOM更新的节奏,就会一直拿到旧值。
解决方案
调试阶段修正控制台输出逻辑
如果需要准确获取某一时刻的DOM文本快照,不要直接打印DOM节点引用,要直接打印读取到的文本值,避免控制台的实时引用机制误导判断:
const currEl = document.getElementById('currgamename'); console.log('当前时刻题目文本:', currEl.textContent);
调整脚本执行逻辑
- 删除无意义的
innerHTML = 'hello'篡改操作,不要修改题目元素本身的内容,避免干扰页面正常逻辑 - 替换固定盲等的轮询逻辑,使用
MutationObserver监听题目元素的文本变化,等新题目真实渲染完成后,再执行计算、填答案、点下一题的操作 - 增加题目格式校验,避免读取到被篡改的非题目内容
调整后的参考代码:
const gameEl = document.getElementById('currgamename'); const inputEl = document.getElementById('gameinput'); const nextBtn = document.getElementById('nextButton'); // 监听题目元素的文本变化,渲染完成后自动解题 const equationObserver = new MutationObserver(() => { const equationText = gameEl.textContent.trim(); // 仅处理标准减法题格式,跳过其他非题目内容 if (!/^\d+-\d+$/.test(equationText)) return; const [leftNum, rightNum] = equationText.split('-').map(Number); const answer = leftNum - rightNum; inputEl.value = answer; nextBtn.click(); }); equationObserver.observe(gameEl, { childList: true, characterData: true, subtree: true }); // 延迟1秒触发首次开始游戏的点击操作 setTimeout(() => { document.getElementById('playPadding').childNodes[1].click(); }, 1000);
内容的提问来源于stack exchange,提问作者fireguy187
相关产品推荐
相关产品推荐

