未捕获的类型错误:无法读取 null 的属性(正在读取“addEventListener”)Chrome 扩展

Posted

技术标签:

【中文标题】未捕获的类型错误:无法读取 null 的属性(正在读取“addEventListener”)Chrome 扩展【英文标题】:Uncaught TypeError: Cannot read properties of null (reading 'addEventListener') Chrome Extension 【发布时间】: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 部分。 我删除了它,但我仍然收到同样的错误? 【参考方案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)

以上是关于未捕获的类型错误:无法读取 null 的属性(正在读取“addEventListener”)Chrome 扩展的主要内容,如果未能解决你的问题,请参考以下文章

如何修复未捕获的类型错误:无法读取 null 的属性“值”

未捕获的类型错误:无法读取 null 的属性“setThemingColor”

未捕获的类型错误:无法读取 null 的属性“querySelectorAll”

未捕获的类型错误无法读取 null 的属性(读取“查询选择器”)

未捕获的类型错误:无法读取 null 的属性“提交”以进行条带支付

未捕获的类型错误:无法读取 null 的属性(读取“添加”)