我正在编写一个Chrome扩展程序,我有这个页面:
<html>
<body>
<button id="changeColor"></button>
<script src="popup.js"></script>
</body>
</html>
有了这个JS(弹出窗口.js):
let changeColor = document.getElementById("changeColor");
chrome.storage.sync.get("color", ({ color }) => {
changeColor.style.backgroundColor = color;
});
changeColor.addEventListener("click", async () => {
let [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
chrome.scripting.executeScript({
target: { tabId: tab.id },
function: setPageBackgroundColor,
});
});
function setPageBackgroundColor() {
chrome.storage.sync.get("color", ({ color }) => {
document.body.style.backgroundColor = color;
});
// Here, it says: Uncaught ReferenceError: getElementByXpath is not defined
console.log(getElementByXpath("xpath").textContent);
}
function getElementByXpath(path) {
return document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}
为什么?
问题:未注入外部函数的代码。
以下是 executeScript 的作用:
- 它将函数的代码作为纯文本 IIFE,即
(function foo() { ... })()
, - 它将文本传输到网页,
- 它选择默认情况下运行扩展的所有内容脚本的
ISOLATED
环境,或者所有页面脚本运行的不安全MAIN
环境(如果显式指定), - 它将该文本作为 JavaScript 代码执行。
解决方案:将所有必要的代码和函数放在您注入的函数中。
在你的例子中,getElementByXpath定义应该移动到setPageBackgroundColor中。
附言:当然,注入的代码也可以通过 manifest.json 的content_scripts
(假设它们的run_at已经发生)或executeScript
使用以前注入的内容脚本的全局变量/函数。