我想使用Chrome扩展程序下载当前页面的DOM。我不确定原因,但是当我下载时,结果只是一个文本文件,其中包含' null'或者' undefined'而不是DOM。我试图吸收来自here和here的知识,但我似乎无法从content.js
到popup.js
收到消息。< / p>
此外,我不确定为什么this确实有效。当我阅读docs时,似乎我需要通过选择有效标签将消息从popup.js
发送到content.js
:
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {message: 'getMessageFromContent'}, function(response) {
//Code to handle response from content.js
}
});
我目前的代码:
content.js
var page_html = DOMtoString(document);
chrome.runtime.sendMessage({method: 'downloadPageDOM', pageDOM: thisPage});
function DOMtoString(document_root) { ... }
background.js
chrome.tabs.query({currentWindow: true, active: true}, function(tab) {
var page_html;
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.message == 'downloadPageDOM')
page_html = request.pageDOM;
else if (request.message == 'getPageDOM')
sendResponse(page_html);
});
});
popup.js
document.addEventListener('DOMContentLoaded', function() {
var download_button = document.getElementById('download_button');
download_button.addEventListener('click', function() {
chrome.runtime.sendMessage({message:'getPageDOM'}, function(response) {
download(response, "download.html", "text/html");
});
});
});
function download(data, fileName, mimeType) { ... }
我觉得我错过了对消息传递如何工作的重要理解。如果有人可以花一点时间来帮助我理解为什么下载的文件只有&#39; null&#39;,我会非常感激。
答案 0 :(得分:2)
你过度复杂,导致很多逻辑错误。
您已将背景页面设置为充当消息代理,内容脚本本身会触发更新page_html
变量。然后弹出窗口会用另一条消息拉出该数据。
请注意,page_html
在任何情况下都不会包含当前标签的数据:您使用上一个加载的标签覆盖了此数据。
你能做的就是完全切断中间人(即background.js
)。我猜你很困惑,因为向弹出窗口发送消息通常是一个坏主意(不保证它是开放的),但反过来通常是安全的(并且你可以使它始终安全)。
您的应用的逻辑是:用户点击该按钮后,立即制作快照。因此,不要让内容脚本立即执行其工作,而是添加一个消息监听器:
// content.js
chrome.runtime.onMessage(function(message, sender, sendResponse) {
else if (request.message == 'getPageDOM')
sendResponse(DOMtoString(document));
});
function DOMtoString(document_root) { ... }
在你的弹出窗口中,请求它:
// popup.js
// (Inside the click listener)
chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
// Note that sending a message to a content script is different
chrome.tabs.sendMessage(tabs[0].id, {message:'getPageDOM'}, function(response) {
download(response, "download.html", "text/html");
});
});
然而,此解决方案不是100%健壮。如果内容脚本未注入页面(and this can happen),则会失败。但是可以解决这个问题。
我们不假设注入了内容脚本。事实上,大多数情况下,只有当用户点击你的按钮时,你才不需要自动注入它。
因此,请从清单中删除内容脚本,确保host permissions("<all_urls>"
运行良好,但考虑activeTab
permission),并使用programmatic injection。< / p>
有一种很少使用的编程注入形式,它收集最后执行的语句的值。我们打算用它。
// content.js
DOMtoString(document); // This will be the last executed statement
function DOMtoString(document_root) { ... }
在弹出窗口中,执行脚本,收集结果:
// popup.js
// (Inside the click listener)
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "content.js"}, function(data) {
// Data is an array of values, in case it was executed in multiple tabs/frames
download(data[0], "download.html", "text/html");
});
});
注意:以上所有内容均假设您的功能DOMtoString
确实有效。