如何将数据从内容脚本传递到页面级?

我正在将所有js代码注入首页,但它需要ui和stuff的图片,只能在chrome.extension.getUrl的帮助下导入,并且只能从content-script调用,所以我发现大量的建议如何将数据传递到内容页面,而没有关于如何传回数据,是否可能呢?

我的代码现在看起来像这样:

我的js代码,将注入其他代码:

var Content = {}; $(document).contentReady = function(content) { Content = content; $(document).ready(function () {/*cool stuff here, that require content*/}); } var event = new CustomEvent('LoadContent'); window.dispatchEvent(event); 

内容脚本:

 document.querySelector('head').appendChild(jsCode); window.addEventListener("LoadContent", function(evt) { var content = { data: "url(" + chrome.extension.getURL('content.smth') + ")" }; document.contentReady(content); }, false); 

显然,我得到document.contentReady is not a function但是在文档中声明函数是关于如何在大约2小时的谷歌搜索后从内容脚本传回数据的唯一(!)建议。

没有什么可以阻止你进行双向的基于CustomEvent的通信,它可以传递带有detail属性的数据:

 // Page script window.addEventListener('RecieveContent', function(evt) { // do something cool with evt.detail }); var event = new CustomEvent('LoadContent'); window.dispatchEvent(event); // Content script window.addEventListener('LoadContent', function(evt) { content = /* ... */ var event = new CustomEvent('RecieveContent', {detail: content}); window.dispatchEvent(event); }); 

这里可以找到更深入的答案。

但是,您应该问自己是否需要页面级脚本来查询数据,因为您可以完全控制何时注入数据。 确保代码执行后,您可以使用单向方法:

 // Page script window.addEventListener('RecieveContent', function(evt) { // do something cool with evt.detail }); // Content script jsCode.onload = function() { // This fires after the page script finishes executing content = /* ... */ var event = new CustomEvent('RecieveContent', {detail: content}); window.dispatchEvent(event); } document.querySelector('head').appendChild(jsCode); 

您可以通过创建新的脚本标记将JS数据传递到页面。 例如:

 function injectScript(code) { var body = document.getElementsByTagName('body')[0]; var s = document.createElement('script'); s.innerHTML = code; body.appendChild(s); } injectScript('var foo = 2;'); 

因此,对于您的特定示例,您应该能够:

 injectScript('document.contentReady({data: url(' + blahblah + '})'); 

不漂亮(当你正在使用覆盖内容脚本时是什么时候?)但是它有效。

Content Scripts不与页面上的普通脚本共享窗口对象。 它们都适用于不同的环境。

在您的情况下,您正在窗口上注册事件侦听器并在其他上下文(窗口)上侦听事件。 因此,永远不会调用您的事件侦听器。

但是,我可以看到在内容脚本和普通脚本之间进行通信的另一种方法是使用MutationObserver

理念

  1. 定义具有某个Id的节点,在该节点下,您将创建与事件对应的子节点。
  2. 在脚本中注册Mustation Observer。
  3. 从内容脚本中,将包含数据的节点添加为data-* api。

实施例

内容脚本

 var submitEvent = function(category, action, label) { var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'), $eventEl = $('').attr({ 'data-category': category, 'data-action': action, 'data-label': label }); eventObserverPlaceholder.appendChild($eventEl.get(0)); }; 

用于注册变异观察者的普通脚本:

 RQ.Methods.addObserverForEvents = function(targetNode) { var observer = new MutationObserver(RQ.Methods.handleMutationList); // Notify me when a new child is added var observerConfig = { attributes: false, childList: true, characterData: false }; observer.observe(targetNode, observerConfig); return observer; }; RQ.mutationObserver = RQ.Methods.addObserverForEvents(document.getElementById('events-observer-placeholder')); 

链接

  1. https://davidwalsh.name/mutationobserver-api
  2. https://developer.mozilla.org/en/docs/Web/API/MutationObserver

工作实例:

我在Requestly Chrome Extension中使用了相同的方法向Google Analytics提交活动。

  1. 内容脚本: https : //github.com/requestly/chrome-extension/blob/master/src/Shared/utils.js#L26
  2. 普通脚本: https : //github.com/requestly/web/blob/gh-pages/js/scripts/tracker.js#L35