Chrome扩展如何将数据从内容脚本发送到popup.html
Chrome Extension how to send data from content script to popup.html
我知道很多帖子都问过这个问题,但老实说我不明白。我是JavaScript、Chrome扩展插件和所有东西的新手,我有这个类作业。因此,我需要制作一个插件,使用跨域请求计算任何给定页面上的DOM对象。到目前为止,我已经能够使用Chrome扩展API实现这一点。现在的问题是,我需要在popup.html页面上显示contentScript.js文件中的数据。我不知道如何做到这一点。我试着阅读了文档,但在chrome中发信息,我就是不明白该怎么做。
以下是迄今为止的代码。
manifest.json
{
"manifest_version":2,
"name":"Dom Reader",
"description":"Counts Dom Objects",
"version":"1.0",
"page_action": {
"default_icon":"icon.png",
"default_title":"Dom Reader",
"default_popup":"popup.html"
},
"background":{
"scripts":["eventPage.js"],
"persistent":false
},
"content_scripts":[
{
"matches":["http://pluralsight.com/training/Courses/*", "http://pluralsight.com/training/Authors/Details/*", "https://www.youtube.com/user/*", "https://sites.google.com/site/*", "http://127.0.0.1:3667/popup.html"],
"js":["domReader_cs.js","jquery-1.10.2.js"]
//"css":["pluralsight_cs.css"]
}
],
"permissions":[
"tabs",
"http://pluralsight.com/*",
"http://youtube.com/*",
"https://sites.google.com/*",
"http://127.0.0.1:3667/*"
]
popup.html
<!doctype html>
<html>
<title> Dom Reader </title>
<script src="jquery-1.10.2.js" type="text/javascript"></script>
<script src="popup.js" type="text/javascript"></script>
<body>
<H1> Dom Reader </H1>
<input type="submit" id="readDom" value="Read DOM Objects" />
<div id="domInfo">
</div>
</body>
</html>
eventPage.js
var value1,value2,value3;
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.action == "show") {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.pageAction.show(tabs[0].id);
});
}
value1 = request.tElements;
});
popup.js
$(function (){
$('#readDom').click(function(){
chrome.tabs.query({active: true, currentWindow: true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, {action: "readDom"});
});
});
});
contentScript
var totalElements;
var inputFields;
var buttonElement;
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse){
if(request.action == "readDom"){
totalElements = $("*").length;
inputFields = $("input").length;
buttonElement = $("button").length;
}
})
chrome.runtime.sendMessage({
action: "show",
tElements: totalElements,
Ifields: inputFields,
bElements: buttonElement
});
任何帮助都将不胜感激,请避免我所做的任何事情:)
尽管您肯定朝着正确的方向前进(而且实际上非常接近尾声),但代码中存在一些(imo)错误做法(例如,为这样一个琐碎的任务注入整个库(jquery)、声明不必要的权限、对API方法进行超级糟糕的调用等)
我自己没有测试你的代码,但从快速的概述来看,我相信纠正以下内容可能会产生一个有效的解决方案(尽管不是很接近最佳):
- 在manifest.json中:更改内容脚本的顺序,将jquery放在第一位。根据相关文档:
"js";[…]要注入到匹配页面中的JavaScript文件的列表。这些元素按照它们在此数组中出现的顺序被注入。
(强调矿)
- 在contentscript.js中:将chrome.runtime.sendMessage({…})块移动到内部的
onMessage
侦听器回调
也就是说,这是我提出的方法:
控制流程:
- 在每个页面中注入一个符合某些条件的内容脚本
- 注入后,内容脚本会向事件页面(也称为非持久后台页面)发送一条消息,事件页面会将页面操作附加到选项卡上
- 页面操作弹出窗口一加载,就会向内容脚本发送一条消息,询问所需信息
- 内容脚本处理请求,并作出响应,以便页面操作弹出窗口可以显示信息
目录结构:
root-directory/
|__img
|__icon19.png
|__icon38.png
|__manifest.json
|__background.js
|__content.js
|__popup.js
|__popup.html
manifest.json:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"offline_enabled": true,
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["*://*.stackoverflow.com/*"],
"js": ["content.js"],
"run_at": "document_idle",
"all_frames": false
}],
"page_action": {
"default_title": "Test Extension",
//"default_icon": {
// "19": "img/icon19.png",
// "38": "img/icon38.png"
//},
"default_popup": "popup.html"
}
// No special permissions required...
//"permissions": []
}
background.js:
chrome.runtime.onMessage.addListener((msg, sender) => {
// First, validate the message's structure.
if ((msg.from === 'content') && (msg.subject === 'showPageAction')) {
// Enable the page-action for the requesting tab.
chrome.pageAction.show(sender.tab.id);
}
});
content.js:
// Inform the background page that
// this tab should have a page-action.
chrome.runtime.sendMessage({
from: 'content',
subject: 'showPageAction',
});
// Listen for messages from the popup.
chrome.runtime.onMessage.addListener((msg, sender, response) => {
// First, validate the message's structure.
if ((msg.from === 'popup') && (msg.subject === 'DOMInfo')) {
// Collect the necessary data.
// (For your specific requirements `document.querySelectorAll(...)`
// should be equivalent to jquery's `$(...)`.)
var domInfo = {
total: document.querySelectorAll('*').length,
inputs: document.querySelectorAll('input').length,
buttons: document.querySelectorAll('button').length,
};
// Directly respond to the sender (popup),
// through the specified callback.
response(domInfo);
}
});
popup.js:
// Update the relevant fields with the new data.
const setDOMInfo = info => {
document.getElementById('total').textContent = info.total;
document.getElementById('inputs').textContent = info.inputs;
document.getElementById('buttons').textContent = info.buttons;
};
// Once the DOM is ready...
window.addEventListener('DOMContentLoaded', () => {
// ...query for the active tab...
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
// ...and send a request for the DOM info...
chrome.tabs.sendMessage(
tabs[0].id,
{from: 'popup', subject: 'DOMInfo'},
// ...also specifying a callback to be called
// from the receiving end (content script).
setDOMInfo);
});
});
popup.html:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
<h3 style="font-weight:bold; text-align:center;">DOM Info</h3>
<table border="1" cellpadding="3" style="border-collapse:collapse;">
<tr>
<td nowrap>Total number of elements:</td>
<td align="right"><span id="total">N/A</span></td>
</tr>
<tr>
<td nowrap>Number of input elements:</td>
<td align="right"><span id="inputs">N/A</span></td>
</tr>
<tr>
<td nowrap>Number of button elements:</td>
<td align="right"><span id="buttons">N/A</span></td>
</tr>
</table>
</body>
</html>
您可以使用localStorage。您可以将任何数据以哈希表格式存储在浏览器内存中,然后随时访问。我不确定我们是否可以从内容脚本访问localStorage(它以前被阻止过),请尝试自己访问。以下是如何通过后台页面进行操作(我首先将数据从内容脚本传递到后台页面,然后将其保存在localStorage中):
在contentScript.js:中
chrome.runtime.sendMessage({
total_elements: totalElements // or whatever you want to send
});
在eventPage.js(您的后台页面)中:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse){
localStorage["total_elements"] = request.total_elements;
}
);
然后,您可以使用localStorage["total_elements"]访问popup.js中的该变量。
也许您可以在现代浏览器中直接从内容脚本访问localStorage。然后您就不需要通过后台页面传递数据了。
关于localStorage的精彩阅读:http://diveintohtml5.info/storage.html
我将为您提供一个简单的解决方案
问题是如何将消息从内容脚本发送到弹出窗口,而不是弹出到内容脚本
在弹出窗口中,您必须从弹出发送消息
document.addEventListener('DOMContentLoaded', function() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {type:"msg_from_popup"}, function(response){
alert(response)
});
});
})
在内容脚本中,您必须添加事件侦听器,但问题是您必须返回true这意味着您可以异步使用sendResponse,如果您没有提到返回true,它将同步工作,您必须立即返回sendResponse消息
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if(request["type"] == 'msg_from_popup'){
console.log("msg receive from popup");
sendResponse("msg received and sending back reply");// this is how you send message to popup
}
return true; // this make sure sendResponse will work asynchronously
}
);
- HTML标记在脚本标记中工作
- 导入jQuery脚本获胜'我不处理html文件
- W3验证器->使用<脚本类型=“;text/javascript”>在html的正文中
- HTML文档中脚本标记的位置-<头部>&<身体>有不同的行为
- 如何逃离<脚本>jquery html()中的标记.我使用了innerHTML和outerHTML来解决这个
- 我的html表单无法验证.请参阅代码片段中的html代码和java脚本
- "未捕获类型错误/丢弃意外“;因为一句台词而出现?(HTML w/<脚本>)
- 在HTML中,如果第二次加载相同的脚本文件,它还会被加载吗
- 在包含脚本的地方注入HTML
- 谷歌应用程序脚本html服务和加载谷歌地图javascript api V3
- Chrome扩展程序/根据弹出窗口中的选择执行不同的内容脚本.html
- 从谷歌应用脚本 html 模板呈现 html
- 将 html 数据与内联脚本 html 数据追加并打印
- 谷歌应用程序脚本HTML服务-Can't get Keypress to work
- Google表单脚本&HTML不能执行被调用的脚本
- 表日期列格式化与谷歌应用程序脚本html服务
- 谷歌脚本不显示jQuery布局时,上传到谷歌脚本HTML
- Google apps脚本HTML选择从电子表格数据加载的选项
- 应用程序脚本HTML到PDF
- 谷歌应用程序脚本HTML应用程序中的谷歌图表