Chrome 插件在新开页生效

Chrome 插件要在当前页面生效后,对从该页面点击打开的"其他页面(新标签页或同标签页跳转)"也生效,通常取决于你的插件是如何注入脚本的。

这里有几种常见的场景和对应的解决方案(均基于目前主流的 Manifest V3):


方法一:通过 manifest.json 自动匹配匹配规则(最简单、最常用)

如果你的插件功能是始终需要 在某些特定的网站上运行的,不需要用户手动点击插件图标触发,那么直接在 manifest.json 中配置 content_scripts 即可。

json 复制代码
{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": [
        "*://*.example.com/*", 
        "https://www.google.com/*"
      ],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ]
}

原理 :只要新打开的页面 URL 匹配 matches 里的规则,Chrome 就会自动将 content.js 注入到新页面中,无需额外写代码。如果想对所有网页生效,可以使用 "<all_urls>"


方法二:通过 Background 脚本监听新页面加载(适合用户手动开启/关闭的插件)

如果你的插件是:用户点击插件图标(Action)后才在当前页面生效 。那么默认情况下,新开的标签页是不会生效的。你需要通过 background.js (Service Worker) 来记住插件的"开启状态",并在新页面加载时动态注入脚本。

1. 修改 manifest.json 添加权限:

json 复制代码
{
  "permissions": ["tabs", "scripting", "storage", "activeTab"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "background.js"
  }
}

2. 编写 background.js 你需要记录当前插件是否处于"激活"状态。

javascript 复制代码
// 监听插件图标点击事件
chrome.action.onClicked.addListener((tab) => {
  // 读取当前状态并切换
  chrome.storage.local.get(['isActive'], (result) => {
    let newState = !result.isActive;
    chrome.storage.local.set({ isActive: newState });
    
    // 如果开启,立刻对当前页面注入脚本
    if (newState) {
      injectScript(tab.id);
    }
  });
});

// 监听标签页更新(当点击链接在当前页跳转,或打开新标签页时会触发)
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  // 确保页面加载完成,并且有 URL
  if (changeInfo.status === 'complete' && tab.url) {
    chrome.storage.local.get(['isActive'], (result) => {
      // 如果插件处于全局开启状态,则自动注入
      if (result.isActive) {
        injectScript(tabId);
      }
    });
  }
});

// 注入脚本的公共方法
function injectScript(tabId) {
  chrome.scripting.executeScript({
    target: { tabId: tabId },
    files: ['content.js']
  }).catch(err => console.log("注入失败:", err));
}

方法三:只针对"从当前已激活页面衍生出的新页面"(精准继承)

如果你不希望插件全局开启,只希望"从激活了插件的页面 A" 点击链接打开的"页面 B" 也被激活 。 你可以利用 chrome.tabs.onCreated 中的 openerTabId 属性。

background.js 中:

javascript 复制代码
// 用一个 Set 来存储被激活了插件的 Tab ID
let activeTabs = new Set();

chrome.action.onClicked.addListener((tab) => {
  // 激活当前 Tab
  activeTabs.add(tab.id);
  injectScript(tab.id);
});

// 监听新标签页被创建
chrome.tabs.onCreated.addListener((tab) => {
  // 如果新标签页是从一个已经激活的 Tab 中打开的 (openerTabId)
  if (tab.openerTabId && activeTabs.has(tab.openerTabId)) {
    // 将新标签页也加入激活列表
    activeTabs.add(tab.id);
  }
});

// 监听标签页加载完成
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status === 'complete' && activeTabs.has(tabId)) {
    injectScript(tabId);
  }
});

// 标签页关闭时清理内存
chrome.tabs.onRemoved.addListener((tabId) => {
  activeTabs.delete(tabId);
});

function injectScript(tabId) {
  chrome.scripting.executeScript({
    target: { tabId: tabId },
    files: ['content.js']
  });
}

方法四:应对单页面应用 (SPA) 如 Vue/React 网站

如果当前网站是单页面应用(如 Bilibili、YouTube 等),点击链接时页面并不会真正刷新,只会通过 HTML5 History API 改变 URL 并局部重新渲染 DOM。

这时上面通过 Background 监听 onUpdated 的方式可能不够及时,你需要在你的 content.js 内部进行监听:

content.js 中监听 URL 变化或 DOM 变化:

javascript 复制代码
// 1. 监听 URL 变化 (拦截 History API)
let lastUrl = location.href; 
new MutationObserver(() => {
  const url = location.href;
  if (url !== lastUrl) {
    lastUrl = url;
    onUrlChange(); // URL发生改变时重新执行你的逻辑
  }
}).observe(document, {subtree: true, childList: true});

function onUrlChange() {
  console.log("页面路由发生改变,重新应用插件效果");
  // 延迟一小段时间等待DOM渲染
  setTimeout(() => {
    applyMyExtensionLogic();
  }, 500);
}

// 你的核心逻辑
function applyMyExtensionLogic() {
  // ...改变背景色、提取数据等
}

// 初始加载执行一次
applyMyExtensionLogic();

总结建议:

  1. 静态且始终生效 :选 方法一 (manifest.json 配置 matches)。
  2. 开关控制,全平台生效 :选 方法二 (Background + chrome.storage)。
  3. 血统继承 (父传子) :选 方法三 (Background + openerTabId)。
  4. 同页面无刷新跳转失效 :选 方法四 (Content script 内 MutationObserver)。
相关推荐
Younglina23 分钟前
打了3年羽毛球球才发现:我对自己的装备和胜率一无所知
前端·后端
风骏时光牛马31 分钟前
Bash脚本高阶实战与常见报错完整代码案例详解
前端
kartjim35 分钟前
我用 AI 一小时写了一个世界杯数据可视化平台|前端 VibeCoding 初体验
前端·程序员·ai编程
lichenyang45335 分钟前
从一个 WebView Demo 开始,理解 ASCF 小程序底座到底在做什么
前端
牧艺36 分钟前
用 Next.js 搭建 AI Agent 前端编排:从 Plan 到 SSE Trace 的完整实践
前端·agent
行者全栈架构师37 分钟前
UniApp集成vk-uview-ui组件库详解:打造高效UI开发体验
前端·vue.js
林希_Rachel_傻希希42 分钟前
js里面的proxy理解。以及vue3响应式数据设计底层
前端·javascript·面试
sunrains42 分钟前
uniapp x 动态Tabbar(切换无闪烁)+动角标+主题切换+自定义tabbar页面导航栏样式设置 支持服务端动态配置根据角色动态设置Tabbar
前端
把马铃薯变成土豆43 分钟前
前端Stripe跨境支付对接感想
前端·源码
牧艺1 小时前
用 Three.js 实现一个浏览器端 3D 看车的项目
前端·three.js