【问题标题】:JQuery on/click functions not working in Chrome ExtensionJQuery on/click 功能在 Chrome 扩展中不起作用
【发布时间】:2017-12-10 20:07:08
【问题描述】:

我正在尝试编写一个简单的 Chrome 扩展程序来从网站上获取有关公寓的信息,但我什至无法从 JQuery 中获取打开/单击功能。

manifest.json

{
  "manifest_version": 2,

  "name": "Flat",
  "description": "Adds flats to app",
  "version": "1.0",

  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": [
    "activeTab",
  ],
  "content_scripts": [
    {
      "matches": [
        "https://www.spareroom.co.uk/flatshare/flatshare_detail.pl*",
      ],
      "js": ["lib/jquery.min.js", "lib/bootstrap.min.js", "content.js"]
    }
  ]
}

content.js

$(document).ready(function () {
    console.log('Viewing flat');
    $("#hello").on("click", function () {
        console.log("Hello");
    });
    $("#hello").click(function () {
        console.log("hello");
    });
});

popup.html

<html>
<head>
    <title>Popup</title>
    <link rel="stylesheet" href="lib/bootstrap.min.css">
    <link rel="stylesheet" href="style.css">
    <script src="lib/jquery.min.js"></script>
    <script src="lib/bootstrap.min.js"></script>
    <script src="content.js"></script>
</head>
<body>
    <div class="container">
        <button id="hello" class="btn btn-default">Add Flat</button>
    </div>
</body>
</html>

我不确定这里的问题是什么。 JQuery 是 3.2.1,Bootstrap 是 3.3.7。这里没有很多与 JQuery 相关的 Chrome 扩展问题。我找到了这个Chrome extensions with jQuery,但我已经有了封装其他代码的文档就绪函数。还查看了这个$(document).click() not working in chrome extension,但该解决方案没有利用 JQuery 的点击/打开功能。

【问题讨论】:

  • 该站点可能会在触发文档就绪事件后动态添加其内容。您可以通过在内容脚本中添加 console.log($("#hello")[0]) 来验证这一点。如果它为空/未定义,则需要通过 setTimeout/setInterval 或 window.onload 或 MutationObserver 等待。
  • 这确实返回 undefined 这对我来说没有意义。我的假设是 $(document) 指的是 popup.html 而不是实际的网页。但这似乎不正确。我不明白什么?
  • 请务必阅读extension architecture overview。内容脚本和弹出窗口都不能直接相互引用,它们运行在浏览器的不同部分。
  • 好吧,我想我得重读一遍,但看起来我得把一些东西移到背景页面。
  • 我看到您也在弹出窗口中包含 content.js。您需要为弹出窗口使用不同的脚本。内容脚本在网页中运行。

标签: jquery google-chrome google-chrome-extension


【解决方案1】:

好吧,这里的问题是我对每个 JS 文件运行的上下文和 Chrome 中的消息传递系统的误解。因此,我将在下面概述对我的代码的更改。可能有更好的方法来做到这一点,但这是我第一次开发 Chrome 扩展程序。

我修改manifest.json如下图

ma​​nifest.json

...
"background": {
    "scripts": ["background.js"]
},
"content_scripts": {
  {
    ...
    "js": ["lib/jquery.min.js"]
  }
}

我添加了后台脚本并将popup.html 中使用的脚本更改为popup.js 而不是content.js

popup.js 如下所示。这是在 popup.html 上的扩展上下文中运行的,并向 Chrome 发送一条消息,启动 background.js 中的处理程序

popup.js

$(document).ready(function () {
    console.log('Viewing flat');
    $("#hello").click(clickHandler);
});

function clickHandler(e) {
     console.log('Adding flat');
     chrome.runtime.sendMessage({directive: "get-flat"}, function (response) {
        //
        console.log("handler", response);
    });
}

background.js 中,我使用chrome.runtime 的onMessage 事件API 创建了一个监听器。然后这将调用chrome.tabs.executeScript,它在实际网页的上下文中执行脚本(content.js)。信使侦听器与Redux w/React 类似,所以这很有趣。我在这个问题上找到了这种模式Detect a button click in the browser_action form of a Google Chrome Extension

background.js

chrome.runtime.onMessage.addListener(
    function (request, sender, sendResponse) {
       switch (request.directive) {
           case "get-flat":
               chrome.tabs.executeScript(null, { file: "content.js" });
               sendResponse("in get-flat directive");
               break;
           case "process":
               console.log("process", request.data);
               break;
            default:
               break;
        }
    }
);

下一部分是content.js,它在网页上下文中运行并抓取我关心的数据。然后它将该消息传递回background.js 以进行进一步操作。为了简洁起见,我简化了代码。

content.js

function getFlat() {
    console.log("in getFlat");
    // Do stuff
    var val = $("#something").text();
    return val;
}
chrome.runtime.sendMessage({directive: "process", data: getFlat()});

我应该提到,我认为 JQuery 在content.js 中工作的唯一原因是因为我从中获取信息的站点也使用了 JQuery。我必须按照background.js 中的tabs.executeScript - passing parameters and using libraries? 的方式将JQuery 注入到上下文中,这样content.js 就可以在不是这种情况下使用它。

编辑

^^ 这是不正确的,因为我是通过 content_scriptsmanifest.json 部分注入 JQuery

结束编辑

无论哪种方式,我都能解决问题。我也以此作为参考Pass a parameter to a content script injected using chrome.tabs.executeScript()

如果有更好的方法,请随时发表评论。就像我说的,这是我第一次尝试 Chrome 扩展。

【讨论】:

  • 您的 manifest.json 似乎暗示您将 popup.js 作为内容脚本和您的 popup.html。这样做几乎总是一个坏主意™。一般来说,您应该只将一个脚本加载到多个上下文中,即一个库(例如 jQuery 等)。如果您尝试在不同的上下文中使用它们,那么专门为在一种上下文中工作而编写的脚本通常会出现问题。这样做是这些标签中许多个问题的来源。
  • 好的,所以我应该删除popup.js 以及引导脚本,因为它将它们注入到网页的上下文中。我想我必须这样做,这样它才能在 popup.html 中工作。我会继续删除它。因此,由于我将 JQuery 作为内容脚本注入,所以我可以在 content.js 中使用它?
  • 是的。仅供参考:弹出窗口和内容脚本上下文是完全分开的。您不/不应该将相同的脚本(库除外)注入到多个不同的上下文中。你可以,但如果你不故意那样编程,这通常需要更多的努力,它只会产生问题。
  • 仅供参考:有 3 种主要上下文类型:背景(由您的扩展程序脚本共享的一种上下文,用于背景、弹出窗口、选项页面以及加载的任何其他 HTML 页面作为选项卡或框架中的顶级文档),内容脚本上下文(对于不是同一域中的父/子的每个页面/框架的不同上下文)和页面上下文(网页脚本运行的位置;每个页面/框架都有一个单独的上下文,带有相同的父/子警告)。对于每个页面/框架(相同的警告),内容脚本和页面脚本共享对 DOM(以及其他一些特殊内容)的访问。
猜你喜欢
  • 2013-12-22
  • 1970-01-01
  • 1970-01-01
  • 2021-01-28
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多