Web扩展内容脚本添加HTML元素异常:按钮短暂显示后消失
问题:Web扩展注入Modrinth页面的按钮短暂显示后消失
我正在开发一款Web扩展,用于实现我的应用与Modrinth网站(地址格式为https://modrinth.com/(mod或resourcepack或shader)/foo)的集成,但在注入新<a>标签时遇到问题——注入的按钮仅短暂出现后就消失了,预期按钮能稳定显示(样式与页面其他iconified-button一致,位置在输入组区域)。
以下是src/onMod.js中的代码:
const main = () => { let inputGroup = document.getElementsByClassName("input-group")[0]; let mcmodpackmanagerbutton = document.createElement("a"); let slug = "sodium"; // Place holder slug = window.location.href.split("/")[4]; // This thing doesn't change mcmodpackmanagerbutton.href = "mcmodpackmanager://modrinthopen?id=" + slug; mcmodpackmanagerbutton.className = "iconified-button"; mcmodpackmanagerbutton.innerHTML = "Open with Minecraft Modpack Manager"; mcmodpackmanagerbutton.setAttribute("rel", "noopener nofollow"); // Other links on modrinth.com use this console.log("SLUG: " + slug); inputGroup.appendChild(mcmodpackmanagerbutton); }; main();
原因分析
Modrinth采用动态渲染的前端框架(如React),页面内容会随框架状态更新重新生成。你的代码首次注入按钮成功后,框架重新渲染对应区域时会覆盖原始DOM,导致注入的按钮被清除。
解决方法
1. 用MutationObserver监听DOM变化,自动重注入
通过监听目标容器的DOM变动,在页面重新渲染后再次注入按钮,同时避免重复创建:
const injectButton = () => { // 移除已存在的按钮,防止重复注入 const existingBtn = document.querySelector('a[href^="mcmodpackmanager://modrinthopen"]'); if (existingBtn) existingBtn.remove(); const inputGroup = document.getElementsByClassName("input-group")[0]; if (!inputGroup) return; const btn = document.createElement("a"); const slug = window.location.href.split("/")[4]; btn.href = `mcmodpackmanager://modrinthopen?id=${slug}`; btn.className = "iconified-button"; btn.innerHTML = "Open with Minecraft Modpack Manager"; btn.setAttribute("rel", "noopener nofollow"); inputGroup.appendChild(btn); }; // 首次注入 injectButton(); // 监听DOM变化,实时重注入 const observer = new MutationObserver(() => injectButton()); observer.observe(document.body, { childList: true, subtree: true });
2. 延迟注入,确保页面动态内容加载完成
调整脚本执行时机,等待页面完全渲染后再注入:
// 替换原有的main()调用 window.addEventListener('load', () => { // 延迟1秒确保动态内容渲染完毕,可根据实际情况调整时长 setTimeout(injectButton, 1000); });
3. 缩小监听范围(优化)
如果能找到input-group的父级稳定容器,可以缩小监听范围,减少性能消耗:
const parentContainer = document.querySelector('.some-stable-parent-class'); if (parentContainer) { observer.observe(parentContainer, { childList: true, subtree: true }); }
内容的提问来源于stack exchange,提问作者Mr. Quantum
相关产品推荐
相关产品推荐

