未捕获的类型错误:无法读取 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)。在弹出窗口中,您可以添加按钮和其他元素供用户单击。弹出窗口特定于每个选项卡。打开多个浏览器窗口并点击图标,可以同时打开多个弹窗。
简而言之:当没有这样的按钮时,错误来自于在后台寻找按钮元素;删除清单密钥将防止这种情况发生。
最小的工作示例
manifest.json:background
密钥已删除
"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 的属性“setThemingColor”
未捕获的类型错误:无法读取 null 的属性“querySelectorAll”
未捕获的类型错误无法读取 null 的属性(读取“查询选择器”)