gpt4 book ai didi

javascript - Chrome 扩展程序 : Message Passing (Sending the DOM to popup. js) 返回 'null'

转载 作者:行者123 更新时间:2023-11-30 17:08:37 24 4
gpt4 key购买 nike

我想使用 Chrome 扩展来下载当前页面的 DOM。我不确定为什么,但是当我下载时,结果只是一个带有“null”或“undefined”的文本文件,而不是 DOM。我试图吸收来自 here 的知识和 here ,但我似乎无法将消息从 content.js 传递到 popup.js

此外,我不确定为什么 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) { ... }

我觉得我缺少对消息传递工作原理的重要理解。如果有人能花点时间帮助我理解为什么下载的文件只有“空”,我将不胜感激。

最佳答案

你把它过于复杂化了,这会导致很多逻辑错误。

您已将后台页面设置为充当消息代理,并且内容脚本本身会触发更新您的 page_html多变的。然后弹出窗口会使用另一条消息提取该数据。

请注意 page_html在任何情况下都不会包含当前 选项卡的数据:您正在用最后一个加载 选项卡覆盖此数据。


您可以做的是完全切断中间人(即 background.js )。我猜您对向弹出窗口发送消息通常是一个坏主意这一事实感到困惑(不能保证它是开放的),但相反的方式通常是安全的(并且您可以使其始终安全)。

解决方案 1(不好,但出于教育目的)

您的应用程序的逻辑是:一旦用户点击按钮,在那一刻制作快照。因此,不要让您的内容脚本立即执行它的工作,而是添加一个消息监听器:

// 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% 稳健。如果内容脚本未注入(inject)页面 ( and this can happen ),它将失败。但有可能解决这个问题。

解决方案2

我们不要假设内容脚本已被注入(inject)。事实上,大多数时候你不需要自动注入(inject)它,只有当用户点击你的按钮时才需要。

因此,从 list 中删除内容脚本,确保您有 host permissions ( "<all_urls>" 效果很好,尽管考虑 activeTab permission ),并且使用 programmatic injection .

有一种很少使用的编程注入(inject)形式,它收集最后执行的语句的值。我们将使用它。

// 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确实有效。

关于javascript - Chrome 扩展程序 : Message Passing (Sending the DOM to popup. js) 返回 'null',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27477641/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com