【问题标题】:pushState change - equivalent to Chrome Extension onHistoryStateUpdatedpushState 更改 - 相当于 Chrome 扩展 onHistoryStateUpdated
【发布时间】:2014-09-26 20:45:19
【问题描述】:

我正在将 Chrome 扩展程序移植到 Firefox 扩展程序,由于运行它的网站的性质,我需要监控 pushState

Chrome 扩展有一个方便的方法来处理这个问题:chrome.webNavigation.onHistoryStateUpdated。我在Chrome扩展中的使用方式如下:

chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
  var tabUrl = details.url;
  if (isTabUrlValid(tabUrl)) {
    $.get(tabUrl, function(data) {
    var videoUrl = $(data).find('meta[itemprop=contentURL]').prop('content');
    videoUrl = validateUrl(videoUrl);
    videoUrl5k = make5kUrl(videoUrl);
  });
 }
});

我需要为 Firefox 扩展做同样的事情,但我没有找到任何好的答案。我试过做这里提到的答案:How to get notified about changes of the history via history.pushState?

(function(history) {
  var pushState = history.pushState;
  history.pushState = function(state) {
    if (typeof history.onpushstate == "function") {
        history.onpushstate({state: state});
    }
    var tabUrl = tabs.activeTab.url;
    console.log("UPDATED TAB URL: " + tabUrl);
    if (isTabUrlValid(tabUrl)) {
      $.get(tabUrl, function(data) {
        var videoUrl = $(data).find('meta[itemprop=contentURL]').prop('content');
        videoUrl = validateUrl(videoUrl);
        videoUrl5k = make5kUrl(videoUrl);
      });
    }
    return pushState.apply(history, arguments);
  };
})(window.history);

问题是,当我执行cfx run 时,它会抱怨history/window is undefined,因此永远不会被检测到。我认为这是因为它在 SDK 中,但我不知道有什么好的解决方法。

有什么想法吗?

编辑:我在下面查看了@willma 的答案,我认为这对我不起作用。问题是 URL 是通过 pushState 更新的,而 DOM 不是......有什么好的方法可以复制我在 chrome 扩展中所做的事情吗?

编辑:这是pageMod 部分

pageMod.PageMod({
  attachTo: 'top', // Don't attach to iFrames --> http://goo.gl/b6b1Iv
  include: [URLs],
  contentScriptFile: [data.url("jquery-2.1.1.min.js"),
                      data.url("csScript.js")],
  onAttach: function(worker) {
    worker.port.on('url', function(url) {
      var videoUrl = validateUrl(url);
      videoUrl5k = make5kUrl(videoUrl);
      console.log("--5K URL--: " + videoUrl5k);
    });
  }
});

【问题讨论】:

  • 让我知道答案是否有帮助或者您是否有任何问题。

标签: firefox firefox-addon firefox-addon-sdk pushstate


【解决方案1】:

该历史代码需要使用content script 注入到选项卡中。现在你的逻辑说当历史事件发生时,检查标签 URL 是否有效。

在 Firefox 中,逻辑是相反的:当标签页被打开时,检查它的 URL 是否有效,如果是,然后附加一个脚本来监控历史事件。为此,您需要使用Page Mod


编辑:所有代码

您缺少的一个关键概念是内容脚本和主/库脚本之间的区别。库脚本存储在lib 中,可以访问所有SDK 模块,但无法访问DOM、窗口对象……内容脚本存储在data 中,使用@987654329 注入页面@ 或 tabs 模块,可以访问 dom 和 window 对象,但不能访问任何 SDK 模块。内容脚本本质上类似于附加标准 HTML 页面(使用 <script></script>)的页面脚本,但需要注意的是它们不能与其他页面脚本共享变量,但它们可以与主脚本通信.

我提出这个问题的唯一原因是因为您最初的问题是尝试从主脚本访问 window 对象,而您的小提琴中的问题是您尝试访问内容中的 tabs 模块脚本。如果这仍然令人困惑,那么值得阅读此答案中最上面的链接。

main.js

const { PageMod } = require('sdk/page-mod');

var sendXHR = function(url) {
  // Do something with the new URL
  // See Request Module docs (below) for sending XHRs from main script.
}

const pageMod = PageMod({
  attachTo: 'top',
  include: '*',
  onAttach: function(worker) {
    worker.port.on('newURL', sendXHR);
  }
});

content.js

var sendNewUrlToMain = function() {
  self.port.emit('newURL', location.href);
}

var pushState = window.history.pushState;
window.history.pushState = function(state) {
    if (typeof history.onpushstate == "function") {
        history.onpushstate({state: state});
    }
    sendNewUrlToMain();
    return pushState.apply(history, arguments);
}

window.addEventListener('hashchange', sendNewUrlToMain); 

这里是request module docs,用于制作 XHR。

注意:如果您不想使用请求模块(唯一的原因是您的 chrome 扩展程序已经有标准 XHR 代码并且不想花时间学习/重写该代码),您可以从 content 脚本发送一个标准的XHR,但这样做可能会导致用户关闭选项卡,从而在执行 XHR 回调之前破坏脚本。

【讨论】:

  • 感谢您的回复。如果某些 URL 被命中,我正在使用 Page Mod API 来注入内容脚本。但是,在我使用有效 URL 加载一个页面并运行内容脚本后,您可以单击一个“相关视频”列表。单击一个后,URL 会更新,但内容脚本永远不会被命中,因为 DOM 未更新,这是由于页面加载了 pushState
  • 您需要将历史监听器放在内容脚本中,而不是放在 main.js 中。所以逻辑是这样的:使用pageMod 来检查原始URL 是否有效。如果是这样,请注入具有一些主要功能历史事件侦听器的内容脚本。当事件监听被触发时,检查新的URL是否有效,如果有效,再次调用main函数。
  • 嗯,有趣的方式。谢谢 - 有时间我会试一试;目前正在将我的代码库迁移到一台新的笔记本电脑上,所以我需要一些时间来测试它,但我感谢您的帮助。
  • 好吧,我做了更改,但似乎从未触及历史事件。以下是内容脚本包含的内容:jsfiddle.net/j3y5qqst/3。如果更新了历史状态(假设),那么我想获取当前选项卡 URL,发送 XHR,获取新 URL,然后将其发送回main.js
  • 查看我的更新答案。您将只能从 pushstate 事件访问 new URL,因此如果您想同时访问这两个 URL,则需要将之前的 URL 存储在某处时间。
猜你喜欢
  • 1970-01-01
  • 2013-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
相关资源
最近更新 更多