weird Uncaught TypeError: Cannot set property 'onclick' of null

weird Uncaught TypeError: Cannot set property 'onclick' of null

我目前正在学习开发 google chrome 扩展。我现在正在尝试获取一个按钮来列出控制台中的所有 span 元素。但是,我似乎无法设置按钮的功能并不断收到奇怪的 Uncaught TypeError: Cannot set property 'onclick' of null 错误。

index.html:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>Simple Greeting Dashboard</title>
    <link rel="stylesheet" href="style.css" />
</head>

<body>
    <button id="main-switch">Update prices:</button>
    <script src="main.js" defer></script>
</body>


</html>

main.js:

window.onload = function() {
    console.log("This is working!");

    chrome.runtime.onInstalled.addListener(function() {
        chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
            chrome.declarativeContent.onPageChanged.addRules([{
                conditions: [new chrome.declarativeContent.PageStateMatcher({
                    pageUrl: { hostEquals: 'steamcommunity.com' },
                })],
                actions: [new chrome.declarativeContent.ShowPageAction()]
            }]);
        });
    });

    function update_prices() {
        var elements = document.getElementsByTagName('span');
        console.log("Elements:", elements);
    }
    document.getElementById('main-switch').onclick = update_prices;
};

manifest.json:

{
    "name": "Steam price helper",
    "version": "1.0",
    "description": "Helps with prices on the Steam community market",
    "incognito": "split",
    "background": {
        "scripts": ["main.js"],
        "persistent": true
    },
    "permissions": [
        "activeTab",
        "storage",
        "declarativeContent"
    ],

    "page_action": {
        "default_popup": "index.html",
        "default_icon": {
            "256": "download.png"
        }
    },

    "manifest_version": 2
}

我查看了具有相同问题的其他问题,但 none 这些解决方案似乎有效。提前致谢!

当您在 manifest.json 中声明 background 时,它会创建一个背景页面,其中包含指定的脚本 运行。这是一个隐藏的单独页面。你可以自己调试它 separate devtools.

browser_actionpage_action 弹出窗口也是一个单独的页面。与背景无关script/page。它还具有自己独立的开发工具,您可以通过 right-clicking 在弹出窗口中选择“检查”来访问它。

您可以使用这两个开发工具来调试问题:设置断点,通过 Ctrl-R 或 F5 键重新加载页面,逐步执行代码并实际查看发生了什么,因此无需猜测。

目前你 运行 在两个页面中有相同的 main.js。 因此, main.js 运行 的一个实例在DOM 为空的后台脚本页面自然找不到任何元素。

解决方案是将其拆分为两个脚本。一个脚本将作为注册API东西的后台脚本。另一个脚本将 运行 在弹出窗口中处理 UI 东西。

  1. 在manifest.json声明"background": {"scripts": ["bg.js", "persistent":false]}

  2. 制作bg.js:

    chrome.runtime.onInstalled.addListener(() => {
      chrome.declarativeContent.onPageChanged.removeRules(() => {
        chrome.declarativeContent.onPageChanged.addRules([{
          conditions: [
            new chrome.declarativeContent.PageStateMatcher({
              pageUrl: {hostEquals: 'steamcommunity.com'},
            }),
          ],
          actions: [new chrome.declarativeContent.ShowPageAction()],
        }]);
      });
    });
    
  3. 使popup.js:

    document.getElementById('main-switch').onclick = function () {
      var elements = document.getElementsByTagName('span');
      console.log('Elements:', elements);
    };
    
  4. 将其加载到您的 html:<script src=popup.js></script>

    不需要 deferasync 属性。也不需要 window.load:脚本 当 DOM 准备就绪时已经 运行s 因为这是 HTML.

    中的最后一件事

备注:

  • 要查看控制台输出,请使用本答案开头所述的正确开发工具。
  • 要使 non-matching 站点上的图标变灰,请参阅