【问题标题】:Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') Chrome Extension未捕获的类型错误:无法读取 null 的属性(正在读取“addEventListener”)Chrome 扩展
【发布时间】:2021-12-31 06:11:37
【问题描述】:

我正在制作一个自动填充 chrome 扩展。即,一旦按下按钮,内容网页中的输入表单将由来自 popup.html 的文本填充。从我向按钮添加事件侦听器的位置开始,我收到此“无法读取 null 属性”错误。 [Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')][1]

这是我的 html 文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Autofill</title>
    <link rel="stylesheet" href="style.css">
    
  </head>
  <body>

    <p id="testText">Text to put</p>
  
    <button id="fillForm">Fill!</button>

    
    <script src="app.js" ></script>
  </body>
  
</html>

这是我的 app.js

console.log('background running!!!')
let testtext = document.getElementById('testText')

let button = document.getElementById('fillForm')
button.addEventListener('click', buttonClick);

function buttonClick(){
    params = {
        active: true,
        currentWindow: true
    }
    chrome.tabs.query(params, gotTabs);

    function gotTabs(tabs){
        let text = testtext.innerHTML
        let content = {
        username: text
        } 
        chrome.tabs.sendMessage(tabs[0].id, content);
    }
}

这是我的 content.js

console.log("Receiving message...")
chrome.runtime.onMessage.addListener(gotMessage);

function gotMessage(message, sender, sendReponse){
    document.getElementById('email').value = content.username
    
}

最后,我的 manifest.json

{
    "name": "Resume Autofiller",
    "description": "Build an Extension!",
    "version": "1.0",
    "manifest_version": 2,
    "browser_action":{
        "default_popup": "index.html"
    },
    "permissions": [
        "activeTab",
        "<all_urls>"
    ],
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": [ "content.js" ]
        } 
    ],
    "background": {
        "scripts": ["app.js"]
      }
    
  }

我在网上看到我应该把我的脚本标签放在正文标签的底部,但我仍然得到这个错误。我觉得我正在监督一些明显的事情,因此非常感谢任何帮助。谢谢!! 附件是我得到的错误。 [1]:https://i.stack.imgur.com/GyNXO.png

【问题讨论】:

  • 从 manifest.json 中删除 background 部分。
  • 我删除了它,但我仍然收到同样的错误?

标签: javascript html dom google-chrome-extension addeventlistener


【解决方案1】:

如前所述,从清单中删除背景将解决此问题,但代码示例中似乎存在概念混淆,这就是为什么我想解释为什么此解决方案有效。

名为 app.js 的脚本似乎打算用作弹出脚本,但在示例中用作后台脚本。弹出窗口与背景不同。这将有助于理解这两个扩展部分及其用例之间的区别。为了连贯性,以下解释将参考 MV3 版本和条款。

背景: “后台服务工作者在需要时加载,在空闲时卸载 [...] 围绕扩展所依赖的事件构建背景脚本。定义功能相关的事件允许后台脚本处于休眠状态,直到这些事件被触发,并防止扩展丢失重要的触发器。” (Manage events with service workers) 附加说明:背景实际上是在背景中;没有可见的用户界面。用户不会在后台与按钮进行交互(尽管可以将事件发送到后台以通过消息传递进行进一步处理)。将背景视为单例。

弹出窗口:这是为扩展用户提供 UI 的可能位置之一。通过用户单击扩展图标激活弹出窗口,并在弹出窗口丢失焦点时被销毁(当时关闭选项卡),并在用户点击下次单击图标时再次重新加载。 “与后台脚本一样,必须在清单中声明此文件,以便 Chrome 将其显示在扩展程序的弹出窗口中。为此,请将操作对象添加到清单并将 popup.html 设置为操作的 default_popup。” (Introduce a user interface)。在弹出窗口中,您可以添加按钮和其他元素供用户单击。弹出窗口特定于每个选项卡。打开多个浏览器窗口并点击图标,可以同时打开多个弹窗。

简而言之:当没有这样的按钮时,错误来自于在后台寻找按钮元素;删除清单密钥将防止这种情况发生。


最小的工作示例

ma​​nifest.jsonbackground 密钥已删除

{
  "name": "Resume Autofiller",
  "description": "Build an Extension!",
  "version": "1.0",
  "manifest_version": 2,
  "browser_action":{
    "default_popup": "index.html"
  },
  "permissions": [
    "activeTab",
    "<all_urls>"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": [ "content.js" ]
    }
  ]
}

index.html:没有变化

(style.css 会引发 not found 错误,但与此问题无关)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Autofill</title>
    <link rel="stylesheet" href="style.css">
    
  </head>
  <body>

    <p id="testText">Text to put</p>
  
    <button id="fillForm">Fill!</button>

    
    <script src="app.js" ></script>
  </body>
  
</html>

app.js:更改了日志文本,无重大变化

console.log('popup running!!!')
let testtext = document.getElementById('testText')

let button = document.getElementById('fillForm')
button.addEventListener('click', buttonClick);

function buttonClick(){
    params = {
        active: true,
        currentWindow: true
    }
    chrome.tabs.query(params, gotTabs);

    function gotTabs(tabs){
        let text = testtext.innerHTML
        let content = {
            username: text
        }
        chrome.tabs.sendMessage(tabs[0].id, content);
    }
}

content.js:更改日志输出一点,注释掉分配

chrome.runtime.onMessage.addListener(gotMessage);

function gotMessage(message, sender, sendResponse){
    console.log("Receiving message...")
    console.log('message', JSON.stringify(message));
    // next line has undefined references, commenting out
    // document.getElementById('email').value = content.username
}

【讨论】:

  • 谢谢,我从清单中删除了后台脚本,但是我仍然遇到同样的错误。现在唯一的区别是 Context 输出我所在的当前选项卡,与之前显示的 _generated_background_page.html 形成对比。在线阅读,修复按钮“属性设置为空”的方法是通过检查命名错误或添加 DOMContentLoaded 事件侦听器,我都做了,但我仍然得到同样的错误
  • 好的,让我发布最小的工作示例。我将编辑答案。
  • 后台没有按钮,除非先以编程方式生成。 getElementById 将在检查命名或等待内容加载后继续返回 undefined。背景应该被认为是无头的(虽然在 mv2 中可以查看生成的页面,但实际用户不会看到它)。
  • 哇,这有助于澄清很多事情,我得到了它的工作。非常感激!!!!它与消息传递有关(message.username 而不是 content.username)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-11
  • 2021-03-07
  • 2022-01-20
  • 2021-12-01
  • 2022-07-02
相关资源
最近更新 更多