Chrome 扩展:消息传递(将 DOM 发送到 popup.js)返回“null”

2023-12-11

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

另外,我不确定为什么this实际上有效。当我读到docs,看来我需要从popup.js to 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
    }
});

我当前的代码:

内容.js

var page_html = DOMtoString(document);
chrome.runtime.sendMessage({method: 'downloadPageDOM', pageDOM: thisPage});

function DOMtoString(document_root) { ... }

背景.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) { ... }

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


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

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

注意page_html不会包含current无论如何,选项卡的数据:您将用最后一个数据覆盖此数据loaded tab.


你能做的就是完全省去中间商(即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% 稳健。如果内容脚本没有注入到页面中将会失败(这可能会发生)。但这个问题是可以解决的。

解决方案2

我们不要假设内容脚本已注入。事实上,大多数时候您不需要自动注入它,仅当用户单击您的按钮时才需要。

因此,从清单中删除内容脚本,确保您有主机权限 ("<all_urls>"效果很好,但考虑一下activeTab允许),以及使用程序化注入.

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Chrome 扩展:消息传递(将 DOM 发送到 popup.js)返回“null” 的相关文章

随机推荐