Chrome扩展:如何通过脚本修改popup.html?解决document未定义错误
Chrome扩展MV3:解决Service Worker无法访问Popup DOM的问题
问题描述
通过content script检测用户选中文本,调用API解析后将结果发送给service worker,期望service worker把内容设置到popup.html的指定元素中,但运行时出现以下错误:
Error in event handler: ReferenceError: document is not defined at chrome-extension://kdiniggbkjgmjabohagdehaeeefcbmfi/script.js:4:5
报错原因
- Service Worker运行在无DOM的后台独立上下文,不存在
document对象,无法直接操作Popup的DOM元素。 - 同一个
script.js被同时用作Service Worker和Popup的脚本,两者运行环境完全不同,导致代码逻辑冲突。
修正方案
核心思路
- 拆分脚本:将Service Worker和Popup的逻辑分离为两个独立文件。
- 存储中转数据:Service Worker收到API结果后,存入
chrome.storage.local,由Popup自行读取并更新DOM。 - Popup主动同步数据:Popup打开时读取存储结果,或监听存储变化实时更新。
修改后的完整代码
1. manifest.json
{ "name": "Paraphraser", "version": "1.0.0", "description": "Automatically paraphrases highlighted text", "manifest_version": 3, "action": { "default_popup": "index.html", "default_title": "Paraphraser" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["contentScript.js"] } ], "background": { "service_worker": "background.js" }, "permissions": ["storage"] }
注:新增storage权限,用于在Service Worker和Popup间传递数据
2. contentScript.js
async function fetchData(text) { if (!text.trim()) return; const options = { method: 'POST', headers: { 'content-type': 'application/json', 'X-RapidAPI-Key': '2a513d4a51msh671908e60614124p125a31jsn338e77807b9b', 'X-RapidAPI-Host': 'paraphraser1.p.rapidapi.com' }, body: JSON.stringify({ input: text }) }; try { const res = await fetch('https://paraphraser1.p.rapidapi.com/', options); const record = await res.json(); chrome.runtime.sendMessage({ type: 'PARAPHRASE_RESULT', data: record.output }); } catch (err) { console.error('API请求失败:', err); } } document.addEventListener('mouseup', function() { const selectedText = document.getSelection().toString().trim(); if (selectedText) { fetchData(selectedText); } });
3. background.js(原Service Worker脚本)
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.type === 'PARAPHRASE_RESULT') { chrome.storage.local.set({ paraphrasedText: message.data }, () => { sendResponse({ status: 'success' }); }); return true; // 异步响应需返回true } });
4. index.html(Popup页面)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>paraphraser</title> </head> <body> <h1>Text will show up here</h1> <br> <p id="popup"></p> <script src="popup.js"></script> </body> </html>
5. popup.js(新增Popup脚本)
// Popup打开时读取存储结果 chrome.storage.local.get('paraphrasedText', (result) => { if (result.paraphrasedText) { document.getElementById('popup').textContent = result.paraphrasedText; } }); // 监听存储变化实时更新 chrome.storage.onChanged.addListener((changes, areaName) => { if (areaName === 'local' && changes.paraphrasedText) { document.getElementById('popup').textContent = changes.paraphrasedText.newValue; } });
内容的提问来源于stack exchange,提问作者Nathan George
相关产品推荐
相关产品推荐

