javascript - 尝试在 chrome 扩展程序(JavaScript)中从 default_script 到 content_script 的通信不起作用

标签 javascript google-chrome google-chrome-extension communication content-script

好吧,我正在通过扩展程序更改网站的配色方案,这是我第一次使用 content_scripts 所以是的,我是一个完全的新手,请随意对待我。

问题是 tabs.connect 它不工作,我需要选项卡 ID 还是什么?这是我到目前为止所拥有的:

list .json:

{
  "manifest_version": 2,

  "name": "ROBLOX Color Scheme",
  "description": "Edit the color scheme of the roblox bar! Note: Not created by roblox.",
  "version": "1.0",

  "permissions": [
    "<all_urls>",
    "tabs"
  ],
  "browser_action": {
    "default_icon": "Icon.png",
    "default_popup": "Popup.html"
  },
  "content_scripts": [
    {
      "matches": ["http://www.roblox.com/*"],
      "js": ["ContentScript.js"]
    }
  ]
}

Popup.html:

<!DOCTYPE html>
<html>
    <head>
        <p>Choose a color:</p>
        <input type="color" id="Color" value="">
        <button type="button" id="Button">Change Color!</button>
    </head>
    <body>
        <script src="Script.js"></script>
    </body>

</html>

脚本.js:

function ChangeColor() {
  var TabId;
    chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) {
      TabId = tabArray[0];
    });
  var port = chrome.tabs.connect(TabId, {name: "ColorShare"});
  port.postMessage({Color: document.getElementById("Color").value});
}

document.getElementById('Color').addEventListener("click", ChangeColor);

ContentScript.js:

var Color;
chrome.runtime.onConnect.addListener(function(port) {
  if (port.name == "ColorShare") then {
    port.onMessage.addListener(function(msg) {
      Color = msg.Color;
    });
  }
});

document.getElementsByClassName("header-2014 clearfix")[0].style.backgroundColor = Color;

感谢所有帮助,感谢您花时间回答我的问题!

编辑:由于我自己和回答者的帮助,现在有些文件已经更改,这些文件现在没有错误,但没有任何变化,您可能提供的任何帮助都会很棒!以下是当前代码:

脚本.js:

chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) {
    var TabId = tabArray[0].id;
    var port = chrome.tabs.connect(TabId, {name: "ColorShare"});

    function ChangeColor() {
        port.postMessage({Color: document.getElementById("Color").value});
    }
    document.getElementById('Color').addEventListener("click", ChangeColor);
});

ContentScript.js:

chrome.runtime.onConnect.addListener(function(port) {
    if (port.name == "ColorShare") {
        port.onMessage.addListener(function(msg) {
            document.querySelector("header-2014 clearfix").style.backgroundColor = msg.Color;
        });
    }
});

编辑:这个问题已经解决了。我不得不使用 chrome.storage.sync.set 和 chrome.storage.sync.get,它们完全支持内容脚本!我会尽快发布使用的脚本!

最佳答案

我认为您误解了端口的概念。一个端口用于一个 session 中的多个消息。但是,当 session 结束时,端口将被销毁(例如,关闭选项卡时)。无论如何,您不应该在每次点击时都重新创建端口。

您的一条评论提到刷新页面,这使我认为您希望这种颜色在页面重新加载时保持不变。从用户界面的 Angular 来看,这是有道理的,但您真的应该在一开始就提到这一点。

正如我所说,关闭选项卡(或重新加载)时端口会被破坏。如果你想让这个值持久化,你需要一个存储机制,比如 chrome.storage (您也可以使用本地存储,但前面的链接给出了不这样做的几个原因)。

manifest.json 只需要 "permissions": [ "activeTab", "storage"],。您可能还需要页面操作而不是浏览器操作(或者两者都不想要,我会讲到)。

ContentScript.js:

var myBgColor = false;

chrome.storage.sync.get("myBgColor",function(items) {
    if ( items.myBgColor ) {
        myBgColor = items.myBgColor;
        document.querySelector(".navbar").style.backgroundColor = myBgColor;
    }
});

chrome.runtime.onMessage.addListener(function(request,sender,sendResponse) {
    if ( request.setColor ) {
        document.querySelector(".navbar").style.backgroundColor = request.setColor;
        chrome.storage.sync.set({"myBgColor":request.setColor});
    } else if ( request.getColor ) {
        sendResponse({"myBgColor":myBgColor});
    }
});

我将参数更改为 querySelector,因为我在索引页上找不到您要查找的元素。

Popup.html:

<!DOCTYPE html>
<html>
<body>
<p>Choose a color:</p>
<input type="color" id="color" value="">
<button type="button" id="button">Change Color!</button>
<script src="Script.js"></script>
</body>
</html>

我不确定您为什么要在页面的头部输入内容。

Script.js(但请将您的文件重命名为比 Script.js 更具描述性的名称):

document.getElementById('button').addEventListener("click",function() {
    chrome.tabs.query({currentWindow: true, active: true},function(tabArray) {
        chrome.tabs.sendMessage(tabArray[0].id,{"setColor":document.getElementById("color").value});
    });
});

chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) {
    chrome.tabs.sendMessage(tabArray[0].id,{"getColor":1},setCurColor);
});

function setCurColor(response) {
    if ( response.myBgColor ) {
        document.getElementById("color").value = response.myBgColor;
    }
}

如果之前设置了背景颜色,我们希望 ContentScript.js 加载消息 Script.js。不幸的是,Script.js 仅在我们单击操作图标时才存在。所以我们让 Script.jsContentScript.js 询问当前颜色(如果已设置)。

正如 Ruwanka Madhushan 所注意到的,您的原始脚本失败(部分)是因为您假设异步 chrome.tabs.query 会在继续执行下一行代码之前完成。异步 javascript 非常强大,但它给了你不假设代码已经完成的责任。您需要使用嵌套函数调用,可以匿名(如 Script.js 的 onclick)或通过命名实用程序函数(如 setCurColor)。 (也有 javascript 库可以帮助处理异步函数,但我不知道。)

一切正常,但有一个小问题:Popup.html closes when it loses focus - 在这种情况下,当您单击颜色选择器输入时。 (非常糟糕的)解决方法是调出弹出窗口并右键单击并选择“检查元素”。这将调出弹出窗口的控制台,并防止弹出窗口在您选择颜色时关闭。另一种选择可能是将颜色选择器嵌入弹出窗口内的 iframe 中(我不知道这是否可行)。

但由于我们正在讨论您的扩展选项,最好的选择可能是使用 options page .这也将为您的 html 提供更多空间。例如,您可能需要考虑一个按钮来删除 localStorage.myBgColor,以便您可以恢复默认设置。或者其他自定义网站的选项,因为我希望你不会为了改变颜色而费尽心机。而且它会隐藏操作图标,因为您可能会设置您的选项,然后想忘记现有的扩展程序。

关于javascript - 尝试在 chrome 扩展程序(JavaScript)中从 default_script 到 content_script 的通信不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25588188/

相关文章:

javascript - 如何在鼠标悬停 div 上添加向下箭头

javascript - 如何将 AIML 与 Node.js 结合使用?

javascript - 用于跟踪我的 Google 事件的浏览器扩展

javascript - 仅在主页上加载的脚本出现在其他路由上

javascript - 每 5 秒更改一次 div 的旋转方向

ajax - 在 Chrome 中快速阻止本地主机以测试 AJAX 失败

swift - Swift Process 的 headless Chrome

javascript - 如何使用 Chrome 扩展自动将 YouTube 主页按钮重定向到 "/feed/subscriptions/u"?

google-chrome - Chrome 扩展程序 : (DOM)Debugger API does not work anymore

javascript - 如何在 Webextension 中以正确的权限运行跨域 XHR 请求?