Chrome Extension如何检测网页用户操作及单页应用内导航事件?
解决方案
方案1:使用chrome.webNavigationAPI(推荐,无需注入内容脚本即可在背景页监听)
SPA内部路由跳转大多基于pushState/replaceState实现,chrome.webNavigation的onHistoryStateUpdated事件会在这类调用完成时触发,搭配原有chrome.tabs.onUpdated即可覆盖两类场景:
- 首先在
manifest.json中声明所需权限:"permissions": ["webNavigation"] - 在背景服务工作线程/背景页中添加监听逻辑:
// 监听常规页面加载完成 chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { if (changeInfo.status === 'complete' && tab.url) { // 执行自定义逻辑 console.log('普通页面加载完成', tab.url) } }) // 监听SPA同页路由跳转 chrome.webNavigation.onHistoryStateUpdated.addListener((details) => { // 过滤iframe跳转,仅监听顶层页面 if (details.frameId === 0) { // 执行自定义逻辑 console.log('SPA路由跳转完成', details.url) } })
注意:该方案对仅使用hash变更实现路由的SPA不生效,需使用下方方案2兼容。
方案2:注入内容脚本监听路由变化(全场景覆盖,兼容hash路由)
如果需要兼容hash路由的SPA,或者需要更精细的路由控制,可以通过内容脚本劫持路由API、监听路由事件后和背景页通信实现:
- 第一步:在
manifest.json中声明内容脚本注入规则,Manifest V3示例:"content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"], "run_at": "document_start" } ] - 第二步:编写
content.js内容,劫持路由API并抛出自定义事件:// 劫持pushState、replaceState方法捕获路由变更 const originalPushState = history.pushState history.pushState = function(...args) { originalPushState.apply(this, args) window.dispatchEvent(new CustomEvent('spaRouteChange')) } const originalReplaceState = history.replaceState history.replaceState = function(...args) { originalReplaceState.apply(this, args) window.dispatchEvent(new CustomEvent('spaRouteChange')) } // 监听hash路由变更 window.addEventListener('hashchange', () => { window.dispatchEvent(new CustomEvent('spaRouteChange')) }) // 监听页面首次加载完成 window.addEventListener('load', () => { window.dispatchEvent(new CustomEvent('spaRouteChange')) }) // 路由变更后通知背景页 window.addEventListener('spaRouteChange', () => { chrome.runtime.sendMessage({ type: 'ROUTE_CHANGED', url: window.location.href }) }) - 第三步:在背景服务工作线程/背景页中监听消息即可:
chrome.runtime.onMessage.addListener((message, sender) => { if (message.type === 'ROUTE_CHANGED') { const tabId = sender.tab.id const currentUrl = message.url // 执行自定义逻辑 console.log('路由变更', tabId, currentUrl) } })
提示:如果仅需要监听特定站点的路由变化,可以修改
content_scripts中的matches规则为对应站点的匹配规则,减少不必要的性能消耗。
内容的提问来源于stack exchange,提问作者codemonkey
相关产品推荐
相关产品推荐

