代码在浏览器控制台可运行,但在Tampermonkey中部分逻辑失效
解决Tampermonkey脚本中动态元素无法被捕获的问题
看起来你的问题核心是动态加载的元素在脚本初始运行时还未存在,导致第二个if语句找不到目标元素——毕竟控制台手动执行时,那些带text类的<a>标签已经完全加载出来了,自然能生效。
问题分析
- 第一个
if能生效,是因为带user_link类的元素属于页面初始渲染的内容,脚本在页面加载完成时(默认@run-at document-end)就能遍历到。 - 而带
text类的元素大概率是通过AJAX异步加载、或者页面交互后动态生成的(比如滚动加载评论、对局记录这类内容),脚本初始运行时它们还没被添加到DOM里,所以遍历不到。
最佳解决方案:用MutationObserver监听DOM变化
这是处理动态元素最可靠的方式,它能实时监听DOM的新增、修改,一旦目标元素出现就立即处理。我们可以把重复的GM标识添加逻辑抽成一个函数,再结合监听实现:
// ==UserScript== // @name Lichess GM Tag for WaisKamal // @namespace http://tampermonkey.net/ // @version 0.1 // @description Add GM tag to WaisKamal's links // @author You // @match https://lichess.org/uZIjh0SXxnt5 // @grant none // ==/UserScript== (function() { 'use strict'; // 抽离重复的添加GM标识逻辑 function addGMTag(linkElement) { if (linkElement.href.includes("WaisKamal") && !linkElement.querySelector('.title')) { // 避免重复添加 linkElement.innerHTML = '<span class="title" data-title="GM" title="Grandmaster">GM</span> ' + linkElement.innerHTML; } } // 初始处理已存在的元素 const initialLinks = document.getElementsByTagName("a"); for(let i = 0; i < initialLinks.length; i++) { addGMTag(initialLinks[i]); } // 监听DOM变化,处理新增的元素 const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // 遍历所有新增的节点 mutation.addedNodes.forEach((node) => { if (node.tagName === 'A') { // 如果新增的就是a标签,直接处理 addGMTag(node); } else if (node.querySelectorAll) { // 如果是包含子元素的节点,查找里面的a标签 const linksInNode = node.querySelectorAll('a.user_link, a.text'); linksInNode.forEach(addGMTag); } }); }); }); // 配置监听选项:监听子节点新增和子树变化 observer.observe(document.body, { childList: true, subtree: true }); })();
额外优化点
- 避免重复添加:加了
!linkElement.querySelector('.title')判断,防止同一个链接被多次添加GM标识。 - 精准选择器:可以直接用
querySelectorAll('a.user_link[href*="WaisKamal"], a.text[href*="WaisKamal"]')来定位目标元素,比遍历所有a标签更高效。 - 权限设置:如果后续需要修改样式或其他操作,可以添加对应的
@grant权限,但当前逻辑不需要。
为什么控制台运行有效?
当你在控制台执行代码时,页面已经完成了所有动态内容的加载,那些带text类的a标签已经存在于DOM中,所以能被正常找到并处理。而Tampermonkey脚本默认在页面初始加载完成后就运行,这时候动态元素还没生成,自然找不到。
内容的提问来源于stack exchange,提问作者Mysterious User
相关产品推荐
相关产品推荐

