问题
I'm currently learning to develop a google chrome extension. I'm trying to get a button to list all of the span
elements in the console for now. However, I can't seem to set the function of the button and keep getting a weird Uncaught TypeError: Cannot set property 'onclick' of null
error.
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
}
I've looked at other questions that have the same problem, but none of those solutions seem to work. Thanks in advance!
回答1:
When you declare background
in manifest.json, it creates a background page where the specified scripts run. It's a hidden separate page. You can debug it its own separate devtools.
The browser_action
or page_action
popup is also a separate page. It's not related to the background script/page. It also has its own separate devtools which you can access by right-clicking inside the popup and choosing "Inspect".
You can use both devtools to debug the problem: set breakpoints, reload the page via Ctrl-R or F5 key, step through the code and actually see what happens so there's no need to guess.
Currently you run the same main.js in two pages. So, one instance of main.js runs in the background script's page where DOM is empty and naturally it doesn't find any elements.
The solution is to split it into two scripts. One script will be the background script that registers API stuff. Another script will run in the popup and deal with UI stuff.
In manifest.json declare
"background": {"scripts": ["bg.js", "persistent":false]}
Make 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()], }]); }); });
Make popup.js:
document.getElementById('main-switch').onclick = function () { var elements = document.getElementsByTagName('span'); console.log('Elements:', elements); };
Load it in your html:
<script src=popup.js></script>
No need for
defer
orasync
attributes. No need forwindow.load
either: the script already runs when DOM is ready as it's the last thing in HTML.
Notes:
- To view the console output, use the correct devtools as explained at the beginning of this answer.
- To gray out the icon on non-matching sites, see this answer.
来源:https://stackoverflow.com/questions/64589720/weird-uncaught-typeerror-cannot-set-property-onclick-of-null