Firefox扩展如何在页面URL动态变更时重新运行content script?
问题原因
你遇到的是单页应用(SPA)的典型适配问题:这类站点通过History API操作浏览器地址栏、动态替换DOM内容实现无刷新跳转,不会触发页面重载,所以content script的默认注入机制只会在首次整页加载时触发一次,后续跳转自然不会重新执行,且原有脚本修改的DOM内容会被站点的动态渲染逻辑清除。
可行解决方案
方案1:在content script中监听路由变化(最便捷)
直接修改你的script.js文件,添加路由变化监听逻辑,检测到URL变更时重新执行业务代码即可:
// 封装你的业务逻辑 function runMyScript() { // 此处放入你原本要执行的代码,比如alert("Hello") alert("Hello") } // 首次加载先执行一次 runMyScript() // 监听浏览器前进/后退触发的popstate事件 window.addEventListener('popstate', () => { runMyScript() }) // 劫持pushState、replaceState(这两个API原生不会触发事件,需手动包装) const originalPushState = history.pushState history.pushState = function(...args) { originalPushState.apply(this, args) window.dispatchEvent(new Event('pushstate')) } const originalReplaceState = history.replaceState history.replaceState = function(...args) { originalReplaceState.apply(this, args) window.dispatchEvent(new Event('replacestate')) } // 监听自定义的路由变更事件 window.addEventListener('pushstate', runMyScript) window.addEventListener('replacestate', runMyScript)
注意:如果担心逻辑重复执行,可以加执行状态标记,或者每次执行前先清理上一次脚本插入的DOM、绑定的事件监听。
方案2:用MutationObserver监听DOM变更
如果站点路由逻辑特殊,监听路由事件不可靠,可以监听页面核心容器的DOM变化,配合URL比对判断是否需要重新执行脚本:
let lastUrl = location.href const observer = new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href runMyScript() } }) // 监听整个document的子节点变更,也可以指定站点的根渲染容器减少性能消耗 observer.observe(document, { subtree: true, childList: true })
方案3:后台脚本配合webNavigation API(适合Manifest V2/V3)
如果不想在content script里加监听逻辑,可以在后台脚本中监听webNavigation.onHistoryStateUpdated事件,匹配到example.com的路由变更时,主动向对应标签页注入脚本或者发送消息触发content script执行逻辑:
- 首先在manifest.json中添加权限:
"permissions": ["webNavigation", "*://*.example.com/*"]
- 后台脚本示例:
browser.webNavigation.onHistoryStateUpdated.addListener(details => { // 匹配目标域名时,执行脚本或者发送消息 browser.tabs.executeScript(details.tabId, {file: "script.js"}) }, { url: [{hostSuffix: 'example.com'}] })
内容的提问来源于stack exchange,提问作者Cyber Shadow
相关产品推荐
相关产品推荐

