Firefox 如何在pagemod和widget之间发出和侦听事件?

Firefox 如何在pagemod和widget之间发出和侦听事件?,firefox,firefox-addon,firefox-addon-sdk,Firefox,Firefox Addon,Firefox Addon Sdk,我正在使用插件sdk。我有一个小部件,点击这个小部件后,我想对网站做些什么(无论是修改页面还是阅读深度DOM) 因此,我在阅读后的想法是: 在匹配的url上激活pagemod(在本例中为任意) 单击满足左键单击事件的小部件。然后它会发出窗口小部件单击 Pagemod接收小部件单击事件,并从Pagemod发回名为的事件 from pagemod对网页做了一些修改 我在stdout中看到以下输出: console.log: project: about to emit widget-click co

我正在使用插件sdk。我有一个小部件,点击这个小部件后,我想对网站做些什么(无论是修改页面还是阅读深度DOM)

因此,我在阅读后的想法是:

  • 在匹配的url上激活pagemod(在本例中为任意)
  • 单击满足
    左键单击
    事件的小部件。然后它会发出
    窗口小部件单击
  • Pagemod接收
    小部件单击事件,并从Pagemod
    发回名为
    的事件
  • from pagemod
    对网页做了一些修改
  • 我在stdout中看到以下输出:

    console.log: project: about to emit widget-click
    console.log: project: after emitting widget-click
    
    所以pagemod没有收到该事件,或者它从未设置过。我不确定这个简单的测试用例缺少什么。感谢您的帮助

    这里是
    lib/main.js

    var widgets = require('sdk/widget');
    var pageMod = require("sdk/page-mod");
    var data = require("sdk/self").data;
    var tabs = require("sdk/tabs");
    
    exports.main = function() {
        var widget = widgets.Widget({
            label: "widget label",
            id: "widget-id",
            contentURL: data.url("off.png"),
            contentScriptFile: [data.url("widget.js"), data.url("page.js")]
        });
    
        widget.port.on("left-click", function() {
            console.log("about to emit widget-click");
            widget.port.emit("widget-click", "foo");
            console.log("after emitting widget-click");
        });
    
    
        var page = pageMod.PageMod({
            include: "*",
            contentScriptWhen: "end",
            contentScriptFile: data.url("page.js"),
            onAttach: function(worker) {
                worker.port.on("widget-click", function(msg) {
                    console.log("on widget-click, ready to emit from-pagemod event");
                    worker.port.emit("from-pagemod", "foo");
                });
            }
        });
    };
    
    这里是
    page.js

    self.port.on("from-pagemod", function(msg) {
        console.log("inside from-pagemod listener");
        // read DOM or modify the DOM
    });
    
    this.addEventListener('click', function(event) {
      if(event.button == 0 && event.shiftKey == false)
        self.port.emit('left-click');
    }, true);
    
    这里是widget.js

    self.port.on("from-pagemod", function(msg) {
        console.log("inside from-pagemod listener");
        // read DOM or modify the DOM
    });
    
    this.addEventListener('click', function(event) {
      if(event.button == 0 && event.shiftKey == false)
        self.port.emit('left-click');
    }, true);
    

    端口是内容脚本和附加组件之间的通信通道:您的小部件可以通过Widget.js与其内容交互,您的pagemod可以通过page.js与匹配的网页内容交互。当您执行
    widget.port.emit(“widget click”,“foo”)
    此消息只能由
    widget.js
    使用
    self.port.on('widget-click')
    监听,不能由pagemod实例监听。由于widget和pagemod是共享main.js作用域的对象,因此它们可以通过访问其属性和方法进行对话。

    编辑2,回答实际问题:

    如果您想在内容脚本已附加时对widget上的页面执行某些操作,请在您有权访问
    页面工作程序的地方注册
    widget
    侦听器。您可以通过将
    小部件.port.放在
    pageMod
    onAttach()
    中的
    代码中来实现这一点,但它只适用于最近附加的页面。使其功能化的最佳方法是存储所有工作程序,然后在单击小部件时检查当前选项卡是否有工作程序,如下所示:

    main.jspartial

    page.js

    self.port.on("widget-click", function(msg) {
      console.log("inside widget-click listener");
      // read DOM or modify the DOM
    });
    
    解决方案不起作用的原因是您假设事件以某种方式链接到文件而不是对象


    老答案:你把事情弄得太复杂了

    只需在单击时附加内容脚本(而不是将内容脚本添加到每个页面,除非它接收到事件,否则不会执行任何操作)

    main.js page.js
    编辑:阅读了解更多信息。此外,当您尝试使用SDK执行以前没有执行过的操作时,该页面也是一个很好的起点。这是一个很好的方法,可以退一步,想想其他方法来实现你的目标。

    如果你还展示了widget的来源,这个答案会更好。js@willlma嗨,谢谢。但是pagemod的目的不是运行内容脚本来匹配特定的URL吗?在我的示例中,我确实使用了
    *
    ,但实际上我可以有多个PageMod,每个PageMod都匹配不同的URL,对吗?在这种情况下,需要做什么?根据我的经验,您可以根据页面的URL或用户输入向页面添加内容脚本。您需要同时执行这两项操作的用例是什么?@derman-henson我更新了答案以反映您的要求。如果正确,请将其标记为正确。仍然有兴趣了解您的用例。
    // read DOM or modify the DOM
    //I'm done, I'll send info back to the main script. This is optional
    self.port.emit('message from content script', someVariable);