检测并处理活动 HTML 页面中的按钮点击

Detect and handle a button click in the active HTML page

目前,我正在为 Firefox 创建一个 WebExtension,它会在 6 秒后在活动选项卡的活动 HTML 页面中显示一个小的 div(不是 popup.htmlbrowser_action!)。我做了一个小例子,在 div 中显示了一个按钮。我的问题是我不知道如何检测此按钮的 click 事件以便我可以启动一个功能?目前我在 content.js

处理事件监听器

manifest.json:

{
  "manifest_version": 2,
  "name": "Study06",
  "version": "1.0",
  "description": "My web extension",
  "permissions": [
  "tabs",
    "<all_urls>",
    "alarms"
  ],
  "background": {
    "scripts": ["background.js"]
  }
}

background.js:

browser.alarms.create("", {delayInMinutes: 0.1});
browser.alarms.onAlarm.addListener(injectScript);
function getActiveTab() {
  return browser.tabs.query({active: true, currentWindow: true});
}
function injectScript() {
  getActiveTab().then((tabs) => {
    browser.tabs.executeScript(null, {
      file: "/content.js"
    });
    // send message to contentscript
    browser.tabs.sendMessage(tabs[0].id, {message: "Hello"});
  });
}

6 秒后,将加载 content.js 并向 content.js 发送消息。

content.js:

document.addEventListener('DOMContentLoaded', function() {
  var button = document.getElementById('button_id');
  button.addEventListener('click', function() {
    console.log("CLICK");
  });
});

browser.runtime.onMessage.addListener(createModal);

function createModal(){
  document.getElementsByTagName('body')[0].appendChild(modal1);
}

//create div with button
var modal1 = document.createElement("div");
modal1.style.paddingTop = "100px";
modal1.setAttribute("id", "mymodal1");
modal1.style.position = "fixed";
modal1.style.top = 0;
modal1.style.left = 0;
modal1.style.zIndex = 1000000;
modal1.style.overflow = "auto";
var button1 = document.createElement("button");
button1.setAttribute("id", "button_id");
button1.innerHTML = "Click me";
modal1.appendChild(button1);

content.js 中的事件侦听器不工作。 我还为按钮创建了一个 JavaScript 文件 javascriptForButtonEvent.js,并在清单 content_script 中添加了这个脚本。另外,要在后台脚本中注入此文件,例如:

browser.tabs.executeScript(null, {
      file: "/content.js";
      file: "/javascriptForButtonEvent.js"
    });

但是,这些解决方案对我不起作用(单击按钮时没有任何反应)。有没有办法处理来自活动 HTML 页面的事件?

您的 click 事件侦听器永远不会添加到 DOM。你有:

document.addEventListener('DOMContentLoaded', function() {

注入脚本时,除非您在 document_start 明确注入,否则保证在 DOMContentLoaded 已经触发后 至少 注入您的脚本。 1 假设事件已经触发,并且只触发一次,您的 DOMContentLoaded 侦听器永远不会被调用。由于注入的工作原理,您根本不需要监听 DOMContentLoaded 事件。只需移动初始化,使其在代码的主序列中执行(添加按钮后):

document.getElementById('button_id').addEventListener('click', function() {
    console.log("CLICK");
});

无需搜索您创建的<button>

但是,在这种情况下,您是自己添加此按钮。不用去DOM里找了。您已经有对它的引用。在创建按钮时添加侦听器:

var button1 = document.createElement('button');
button1.id = 'button_id';
button1.textContent = 'Click me';
button1.addEventListener('click', function() {
    console.log("CLICK");
});
modal1.appendChild(button1);

不要使用通用 ID 或 类

对于扩展,您不应使用与 button_id 一样通用的 ID 或 类。这样做很可能会与要向其中注入内容的随机页面发生名称冲突。您应该选择用作 "namespace" 的文本序列。然后,您可以将此命名空间添加到所有 ID 和 类 之前。例如,您的 ID 应该类似于:Study06-button_id。您使用什么是个人选择。但是,它应该特定于您正在使用的扩展程序。

当监听 DOMContentLoaded, you should check readyState

任何时候你使用 DOMContentLoaded 监听器,或者 window load 监听器,你应该总是检查 document.readyState 以确保你正在添加监听器在 DOMContentLoaded 事件被触发之前(或 load 事件,如果那是你正在监听的)。当您想监听这些事件时,这应该是正常的习惯。如果您在事件触发后添加侦听器,则侦听器将永远不会 运行.

要添加 DOMContentLoaded 侦听器,您应该使用如下内容:

if(document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded',afterLoaded);
} else {
    afterLoaded();
}

function afterLoaded(){
    //Everything that needs to happen after the DOM has initially loaded.
}

  1. 请注意,在使用 tabs.executeScript() 时,您必须认真 工作 tabs.executeScript() 在实际注入脚本的时间范围内执行document_start。对于不同的浏览器,所需的确切时间是不同的。如果您使用 manifest.json content_script 条目,则此时间由浏览器处理。