나는 이것이 수많은 게시물에서 요청되었지만 솔직히 이해하지 못한다는 것을 알고 있습니다. 저는 JavaScript, Chrome 확장 프로그램 및 모든 것을 처음 접했고이 수업 과제가 있습니다. 따라서 Cross Domain Requests를 사용하여 특정 페이지에서 DOM 개체를 계산하는 플러그인을 만들어야합니다. 지금까지 Chrome Extension API를 사용하여이를 달성 할 수있었습니다. 이제 문제는 contentScript.js 파일의 popup.html 페이지에 데이터를 표시해야한다는 것입니다. 문서를 읽으려고 시도했지만 크롬으로 메시지를 보내는 방법을 모르겠지만 무엇을 해야할지 이해할 수 없습니다.
다음은 지금까지의 코드입니다.
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