我正在构建我的第一个 Chrome 扩展程序。功能集将会更大,但目前,我正在尝试从活动选项卡获取 HTML 元素。该选项卡将始终是温室网页。
例如,GoDaddy 的这份工作:https://boards.greenhouse.io/godaddy/jobs/5681152003?gh_jid=5681152003#app
所有这些类型的链接都有一个 id="content" 的 HTML 元素。这种划分主要包括段落和无序列表。我只想在我的 popup.html 中打印此内容。无论我如何尝试,它都不起作用。
我对代码可能出错的地方有一些假设(但我无法证明):
- 查找问题: 也许我不应该使用
document.querySelector("#content").querySelectorAll("p, ul > li")
方法来查找我想要的内容。除了 <p>
和 <ul>
(如 <hr>
)之外,该分区内可能还有其他 html 元素,这会造成麻烦。
- 处理
<div>
内部信息的问题: content.js 中的代码将 <div>
内部的信息作为 NodeList 获取,然后迭代该 NodeList 将文本内容推送到需求数组中。也许这不是正确的做法。
- 异步通信: 我必须使函数异步以处理 chrome.runtime.sendMessage() 方法的异步性质。在我的代码中,popup.js 和 content.js 之间的所有通信都是通过 background.js 文件完成的。我怀疑那里可能有问题,但我不明白它是什么。
- Tab 信息问题: 我不知道我是否将 Tab 信息正确发送到 content.js。
我的代码有逻辑错误吗?
我的代码如下:
manifest.json
请注意,我在“content_script”中添加了“run_at”:“document_end”以尝试处理计时问题。
{
"manifest_version": 3,
"name": "Experience Tracker",
"version": "1.0",
"description": "Track your work experiences and match with job requirements.",
"permissions": [
"activeTab"
],
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"run_at": "document_end"
}
],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
popup.html
<!DOCTYPE html>
<html>
<head>
<title>Experience Tracker</title>
<script src="popup.js"></script>
</head>
<body>
<!-- Button that triggers the fetching of job requirements -->
<button id="fetchRequirements">Fetch Job Requirements</button>
<hr>
<h2>Matched Requirements</h2>
<!-- Paragraph element where all the content from <div id="content"> from the Active Tab will be displayed -->
<p id="matchedRequirements"></p>
</body>
</html>
popup.js
popup.js 代码定义了一个名为 fetchRequirements 的函数,该函数从后台脚本获取作业要求。当用户点击 Chrome 扩展弹出窗口中的 fetchRequirements 按钮时,会触发此函数。该代码向后台脚本发送一条消息,请求匹配的要求。收到响应后(应包含
<div id="content">
内的内容),它会为每个需求生成 HTML 元素,并将它们显示在 popup.html 的 <p id="matchedRequirements">
中。该代码还确保获取过程与扩展环境的异步性质保持一致并处理按钮单击事件。
const fetchRequirements = async () => {
const request = {
action: "fetchRequirements"
};
const response = await chrome.runtime.sendMessage(request);
if (response.matchedRequirements) {
const requirementsHtml = response.matchedRequirements.map(requirement => {
return `<div>${requirement}</div><br>`;
}).join("");
document.getElementById("matchedRequirements").innerHTML = requirementsHtml;
}
};
document.addEventListener("DOMContentLoaded", function() {
const fetchRequirementsButton = document.getElementById("fetchRequirements");
const matchedRequirementsList = document.getElementById("matchedRequirements");
fetchRequirementsButton.addEventListener("click", async () => {
await fetchRequirements();
});
});
内容.js
这个 content.js 脚本负责从网页内容中提取职位要求。它查找 ID 为“content”的元素,并查找其中的段落 (
<p>
) 和列表项 (<li>
)。然后它迭代这些元素,提取它们的文本内容,并将其添加到需求数组中。最后,它向后台脚本发送一条消息,使用“fetchRequirements”操作标识符传递提取的需求。
function fetchRequirements() {
const requirements = [];
const contentElements = document.querySelector("#content").querySelectorAll("p, ul > li");
for (const contentElement of contentElements) {
requirements.push(contentElement.textContent);
}
chrome.runtime.sendMessage({
action: "fetchRequirements",
matchedRequirements: requirements
});
}
背景.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.requirements) {
chrome.storage.local.set({ matchedRequirements: request.requirements });
}
});
我预计,当单击 fetchRequirements 按钮时,id =“content”的分区下活动选项卡中的所有内容都将显示在我的 id =“matchedRequirements”的段落中。现在,当我单击 fetchRequirements 按钮时,没有任何反应,并且出现错误:
未捕获(承诺中)类型错误:无法读取未定义的属性(读取“matchedRequirements”)
(代表问题作者发布解决方案并将其移至答案空间).
问题是我没有在文件之间正确通信。 popup.js 没有发送 TabId 信息,并且 popup.js 正在等待从未到来的响应!现在正在工作。