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

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的脚本,两者运行环境完全不同,导致代码逻辑冲突。

修正方案

核心思路

  1. 拆分脚本:将Service Worker和Popup的逻辑分离为两个独立文件。
  2. 存储中转数据:Service Worker收到API结果后,存入chrome.storage.local,由Popup自行读取并更新DOM。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:45:54