You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展Manifest V3:content.js向popup.js传值示例需求

解决方案:Manifest V3 中 Content Script 向 Popup 传递数据

核心逻辑说明

Popup 仅在用户点击扩展图标打开时存在,关闭后即销毁。因此有两种实用方案:

  1. 通过 Background Service Worker 中转存储 + Popup 主动获取:最可靠,适合 Popup 打开时需要获取之前 Content Script 发送的数据
  2. 直接向 Popup 发送消息:仅当 Popup 处于打开状态时有效

方案一:Background 中转存储(推荐)

Content Script 将数据发给 Background 存储,Popup 打开时主动从 Background 拉取数据。

1. manifest.json

{
  "manifest_version": 3,
  "name": "Content to Popup Demo",
  "version": "1.0",
  "permissions": ["storage"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ],
  "action": {
    "default_popup": "popup.html"
  }
}

2. background.js

// 接收 Content Script 数据并存储
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'SEND_TO_BACKGROUND') {
    // 关联标签页 ID 存储,避免不同页面数据混淆
    chrome.storage.local.set({
      [`tab_${sender.tab.id}_content_data`]: request.data
    });
    sendResponse({status: '数据已存储'});
  }
});

// 给 Popup 提供数据查询接口
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'GET_FROM_BACKGROUND') {
    // 获取当前激活标签页的对应数据
    chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
      const tabId = tabs[0].id;
      chrome.storage.local.get([`tab_${tabId}_content_data`], (result) => {
        sendResponse(result[`tab_${tabId}_content_data`] || '暂无数据');
      });
    });
    // 异步操作需返回 true 保持 sendResponse 有效性
    return true;
  }
});

3. content.js

// 页面加载时发送数据到 Background
(async () => {
  const contentData = '这是来自 Content Script 的测试字符串';
  try {
    const res = await chrome.runtime.sendMessage({
      type: 'SEND_TO_BACKGROUND',
      data: contentData
    });
    console.log(res);
  } catch (err) {
    console.error('发送失败:', err);
  }
})();

4. popup.html

<!DOCTYPE html>
<html>
<head>
  <style>body { width: 220px; padding: 15px; }</style>
</head>
<body>
  <div id="dataContainer">加载数据中...</div>
  <script src="popup.js"></script>
</body>
</html>

5. popup.js

// Popup 打开时主动拉取数据
(async () => {
  try {
    const data = await chrome.runtime.sendMessage({
      type: 'GET_FROM_BACKGROUND'
    });
    document.getElementById('dataContainer').textContent = `收到数据:${data}`;
  } catch (err) {
    console.error('获取失败:', err);
    document.getElementById('dataContainer').textContent = '数据获取失败';
  }
})();

方案二:直接向 Popup 发送消息(仅 Popup 打开时有效)

仅当 Popup 处于打开状态时,Content Script 可直接定位 Popup 窗口并发送消息。

1. 修改 content.js

// 尝试直接发送数据到 Popup
async function sendToPopupDirectly() {
  try {
    // 筛选扩展自身的 Popup 窗口
    const allWindows = await chrome.windows.getAll({
      populate: true,
      windowTypes: ['popup']
    });
    const popupWindow = allWindows.find(win => 
      win.urls.some(url => url.startsWith(chrome.runtime.getURL('/')))
    );

    if (popupWindow) {
      const popupTab = popupWindow.tabs[0];
      // 向 Popup 标签页发送消息
      const res = await chrome.tabs.sendMessage(popupTab.id, {
        type: 'SEND_TO_POPUP',
        data: 'Content Script 实时发送的数据'
      });
      console.log('已发送到 Popup:', res);
    } else {
      console.log('Popup 未打开,无法直接发送');
    }
  } catch (err) {
    console.error('直接发送失败:', err);
  }
}

// 可绑定页面事件触发,或页面加载时尝试发送
sendToPopupDirectly();

2. 修改 popup.js

// 监听来自 Content Script 的直接消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type === 'SEND_TO_POPUP') {
    document.getElementById('dataContainer').textContent = `实时收到:${request.data}`;
    sendResponse({status: '已接收'});
  }
});

关键注意事项

  • Popup 生命周期:Popup 关闭后会立即销毁,直接发送消息仅在其打开时有效,推荐使用方案一处理大多数场景。
  • Storage 权限:方案一需要在 manifest 中声明 "permissions": ["storage"] 才能使用存储 API。
  • 异步处理:Chrome 扩展 API 多为异步操作,需使用 async/await 或回调,异步监听时需返回 true 保持 sendResponse 有效。

内容的提问来源于stack exchange,提问作者Serilena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:18:27