将数据(标签)从background.js传递到popup.js

时间:2019-07-24 13:18:16

标签: javascript google-chrome google-chrome-extension

我目前正在尝试创建一个Chrome扩展程序,该扩展程序在其弹出窗口中列出所有打开的标签页。稍后将添加更多功能,例如通过弹出窗口关闭特定标签,使用特定URL打开新标签等。

manifest.json

{
  "manifest_version": 2,
  "name": "List your tabs!",
  "version": "1.0.0",
  "description": "This extension only lists all of your tabs, for now.",
  "background": {
    "persistent": true,
    "scripts": [
      "js/background.js"
    ]
  },
  "permissions": [
    "contextMenus",
    "activeTab",
    "tabs"
  ],
  "browser_action": {
    "default_popup": "popup.html"
  }
}

background.js

const tabStorage = {};
(function() {

    getTabs();

    chrome.tabs.onRemoved.addListener((tab) => {
        getTabs();
    });

    chrome.tabs.onUpdated.addListener((tab) => {
        getTabs();
    });


}());

function getTabs() {
    console.clear();
    chrome.windows.getAll({populate:true},function(windows){
        windows.forEach(function(window){
            window.tabs.forEach(function(tab){
                //collect all of the urls here, I will just log them instead
                tabStorage.tabUrl = tab.url;
                console.log(tabStorage.tabUrl);
            });
        });
    });

    chrome.runtime.sendMessage({
        msg: "current_tabs", 
        data: {
            subject: "Tabs",
            content: tabStorage
        }
    });
}

popup.js

(function() {

    chrome.runtime.onMessage.addListener(
        function(request, sender, sendResponse) {
            if (request.msg === "current_tabs") {
                //  To do something
                console.log(request.data.subject)
                console.log(request.data.content)
            }
        }
    );

}());

根据我的理解,由于您应该在background.js中使用侦听器来更改选项卡。然后,当发生这种情况时,您可以向popup.js

发送消息

如您所见,目前,我只是在将其附加到div或popup.html中的某个内容之前,尝试在控制台中登录我的标签以确保其正常工作。但是,这不起作用,因为在我的popup.html控制台中出现以下错误:

popup.js:3 Uncaught TypeError: Cannot read property 'sendMessage' of undefined

所以我...由于某种限制,我无法在popup.js中使用onMessage,但我也对如何实现我想做的事情一无所知。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

  1. Google关于后台脚本的文档有点含糊。对于您的用例而言,重要的是,弹出窗口仅在显示时才运行,而在隐藏时不运行,因此您根本不需要background.js,只需将所有内容都放入popup.js中即可在您每次运行时运行显示弹出窗口,这是您的popup.html:

    <script src="popup.js"></script>
    
  2. 该错误消息表示您正在直接从磁盘上以file://页的形式打开html文件,但应通过单击扩展名图标或通过其自己的URL chrome-extension:// id来打开它/popup.html,其中id是您的扩展程序ID。当您点击扩展程序图标时,此操作会自动发生-弹出窗口是具有该URL的单独页面,具有自己的DOM,documentwindow等。

  3. 该弹出窗口有其自己的devtool,请参见this answer,其中显示了如何调用它(在Chrome中,通过右键单击弹出窗口内部,然后单击“检查”)。

  4. 扩展API是异步的,因此回调将在外部代码完成后在以后的某个点运行,这就是为什么您不能像目前那样在回调之外使用tabStorage的原因。更多信息:Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference

  5. 应该不必枚举onRemoved和onUpdated中的所有选项卡,因为当打开一百个选项卡时,它可能真的很慢。相反,您可以使用提供给这些事件的侦听器的参数来修改tabStorage,有关详细信息,请参见documentation。这需要tabStorage保留每个标签的ID,因此仅保留来自API的整个响应是有意义的。这是一个简化的示例:

    let allTabs = [];
    
    chrome.tabs.query({}, tabs => {
      allTabs = tabs;
      displayTabs();
    });
    
    function displayTabs() {
      document.body.appendChild(document.createElement('ul'))
        .append(...allTabs.map(createTabElement));
    }
    
    function createTabElement(tab) {
      const el = document.createElement('li');
      el.textContent = tab.id + ': ' + tab.url;
      return el;
    }