Javascript 如何将数据从内容脚本传递到页面级?
我正在将我所有的js代码注入到首页,但它需要用于ui和其他内容的图片,这些图片只能在chrome.extension.getUrl的帮助下导入,并且只能从内容脚本中调用,因此我找到了大量关于如何将数据传递到内容页的建议,而对于如何将数据传递回来的建议却一无所知,这有可能吗 我的代码现在如下所示: 我的js代码,将与其他代码一起注入:Javascript 如何将数据从内容脚本传递到页面级?,javascript,jquery,google-chrome-extension,content-script,Javascript,Jquery,Google Chrome Extension,Content Script,我正在将我所有的js代码注入到首页,但它需要用于ui和其他内容的图片,这些图片只能在chrome.extension.getUrl的帮助下导入,并且只能从内容脚本中调用,因此我找到了大量关于如何将数据传递到内容页的建议,而对于如何将数据传递回来的建议却一无所知,这有可能吗 我的代码现在如下所示: 我的js代码,将与其他代码一起注入: var Content = {}; $(document).contentReady = function(content) { Content = con
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不是一个函数
但在谷歌搜索了大约2个小时后,在文档中声明函数是关于如何从内容脚本传回数据的唯一(!)建议。您可以通过创建新的脚本标记将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 + '})');
不太好看(当您使用覆盖内容脚本时会发生什么情况?),但它可以工作。您可以通过创建新的脚本标记将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 + '})');
不漂亮(当您使用覆盖内容脚本时是什么情况?),但它可以工作。内容脚本
不与页面上的普通脚本共享窗口对象。他们都在不同的背景下工作
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
在本例中,您正在窗口上注册一个事件侦听器,并在其他上下文(窗口)上侦听该事件。因此,您的事件侦听器将永远不会被调用
然而,我可以看到,在内容脚本和普通脚本之间进行通信的另一种方法是使用MutationObserver
主意
定义具有某个Id的节点,在该节点下创建与事件对应的子节点
在脚本中注册集合观察者
从内容脚本中,添加数据为data-*
api的节点
实现示例
内容脚本
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
链接
工作示例:
我在Chrome扩展中使用了相同的方法将事件提交给Google Analytics
内容脚本:
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
正常脚本:
内容脚本
不与页面上的普通脚本共享窗口对象。他们都在不同的背景下工作
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
在本例中,您正在窗口上注册一个事件侦听器,并在其他上下文(窗口)上侦听该事件。因此,您的事件侦听器将永远不会被调用
然而,我可以看到,在内容脚本和普通脚本之间进行通信的另一种方法是使用MutationObserver
主意
定义具有某个Id的节点,在该节点下创建与事件对应的子节点
在脚本中注册集合观察者
从内容脚本中,添加数据为data-*
api的节点
实现示例
内容脚本
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
链接
工作示例:
我在Chrome扩展中使用了相同的方法将事件提交给Google Analytics
内容脚本:
var submitEvent = function(category, action, label) {
var eventObserverPlaceholder = document.getElementById('events-observer-placeholder'),
$eventEl = $('<span></span>').attr({
'data-category': category,
'data-action': action,
'data-label': label
});
eventObserverPlaceholder.appendChild($eventEl.get(0));
};
正常脚本:
没有任何东西可以阻止您进行基于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);
没有任何东西可以阻止您进行基于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);
虽然这是一个更优雅的解决方案,但您只需在页面中插入一个
标记,然后访问主页的执行内容。@gladsocc此方法的优点是,您可以使用此方法在内容脚本和普通脚本之间进行通信。你只需要两个占位符。一开始我看起来有点困惑,但我要试试这个,似乎它会起作用,非常感谢您的回复!虽然这是一个更优雅的解决方案,但您只需在页面中插入一个
标记,然后访问主页的执行内容。@gladsocc此方法的优点是,您可以使用此方法在内容脚本和普通脚本之间进行通信。你只需要两个占位符。一开始我看起来有点困惑,但我要试试这个,似乎它会起作用,非常感谢您的回复!好吧,好吧,看起来很简单,但我怎么能发现,数据已经收到了?好吧,看起来很简单,但我怎么能发现,数据已经收到了?@Madara我不同意重复的说法,但鉴于我的重新投票有可能立即重新开始,我想避免引起(新的)钻石的愤怒。我的理由是:您的副本只显示了一种回答问题的可能途径,而不是它的表述方式:“如何将数据传递回”。dupe目标无法覆盖其他方法(将方法注入窗口
)。这是一个更为普遍的问题,应该取消这个骗局。你的决定似乎是基于现有的答案。你同意吗?@Xan:当然,如果你认为我的决定错了,那就重新打开吧。还有,不要害怕引起我的愤怒。我感谢所有对我的决定的批评。@MadaraUchiha我只是认为不发表评论就这样做是不够的。@Madara我不同意重复投票,但鉴于我的重新投票有可能立即重新投票,我希望避免引起(新的)钻石的愤怒。我的理由是:你的复制品