Chrome扩展Manifest V3:content.js向popup.js传值示例需求
解决方案:Manifest V3 中 Content Script 向 Popup 传递数据
核心逻辑说明
Popup 仅在用户点击扩展图标打开时存在,关闭后即销毁。因此有两种实用方案:
- 通过 Background Service Worker 中转存储 + Popup 主动获取:最可靠,适合 Popup 打开时需要获取之前 Content Script 发送的数据
- 直接向 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
相关产品推荐
相关产品推荐

