在我們平時的開發工作中,chrome開發者工具是我們必不可少的工具,除了Chrome原生的工具之外,還有比如:
- 使用vue開發時使用的 vue-devtools
- 使用react開發時使用的 react-devtools
本文主要分享的就是這些開發者工具怎么與頁面進行消息通信的。
首先,先看一個例子:
這個開發者工具源碼:github.com/HuJiaoHJ/ec…,這個工具是一個支持canvas庫 ( easycanvas ) 的chrome調試工具,能對canvas的元素的樣式、物理屬性等進行修改,達到所見即所得的效果,提高調試效率。感興趣的小伙伴可以自行了解下~
本文主要是通過這個工具,分享一下 chrome devtools 通信相關的知識(chrome devtools的基礎開發在這里就不介紹了,不熟悉的小伙伴可以去官網看看~)當然,沒有接觸過chrome devtools開發的小伙伴,也可以通過這篇文章了解到chrome devtools的基本組成,了解其基本的通信方式,對平時的工作也能有一些借鑒和幫助噠~
chrome devtools 簡單介紹
chrome devtools 主要分為三部分:
- DevTools Page:開發者工具,就是我們平時使用時,接觸到的面板
- Background Page:后台頁面,雖然叫頁面,其實是在后台的js腳本
- Content Script:內容腳本,是在網頁的上下文中允許的js文件
下面會詳細介紹各部分,下面這張圖是這三部分之間的通信全景圖:
我們根據這張圖,來詳細的看看每個部分的具體實現吧~
- 網頁與內容腳本通信
- 內容腳本與后台頁面通信
- 后台頁面與開發者工具通信
- 網頁的消息怎么傳遞到開發者工具?
- 開發者工具的消息怎么傳遞到網頁?
網頁與內容腳本通信
內容腳本(Content Script)是在網頁的上下文中運行的js文件,可以通過此js文件獲取DOM和捕獲DOM事件。
網頁不能直接與開發者工具(DevTools Page)進行通信,需要通過在內容腳本中監聽網頁事件,通過chrome.runtime API將消息傳遞到后台頁面中,從而傳遞到開發者工具中。
內容腳本可以監聽網頁的DOM事件或者window.postMessage事件,如下:
web page
window.postMessage({
name: 'hello wolrd'
}, '*');
復制代碼
content-script.js
window.addEventListener('message', e => {
if (e.source === window) {
chrome.runtime.sendMessage(e.data);
}
});
復制代碼
內容腳本與后台頁面通信
后台頁面,雖然叫頁面,其實是在后台的js腳本。
內容腳本監聽的事件觸發之后,通過chrome.runtime.sendMessage()方法將消息傳遞到后台頁面(Background Page)中。
后台腳本通過chrome.runtime.onMessage.addListener()方法監聽消息,如下:
background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (sender.tab) {
const tabId = sender.tab.id;
......
} else {
console.log("sender.tab not defined.");
}
return true;
});
復制代碼
后台頁面與開發者工具通信
后台頁面與開發者工具通過長連接進行通信。(chrome.runtime API)如下:
devtool.js
// 與后台頁面消息通信-長連接
const port = chrome.runtime.connect({name: 'devtools'});
// 監聽后台頁面消息
port.onMessage.addListener((message) => {
......
});
// 往后台頁面發送消息
port.postMessage({
name: 'original',
tabId: chrome.devtools.inspectedWindow.tabId
});
復制代碼
background.js
chrome.runtime.onConnect.addListener(function (port) {
const extensionListener = function (message, sender, sendResponse) {
if (message.name == 'original') {
......
}
};
port.onMessage.addListener(extensionListener);
port.onDisconnect.addListener(function(port) {
port.onMessage.removeListener(extensionListener);
});
});
復制代碼
以上,就介紹了網頁與內容腳本、內容腳本與后台頁面、后台頁面與開發者工具之間的通信,所以可以發現,網頁的消息是通過內容腳本、后台頁面,最后到達開發者工具,那么達到內容腳本的消息怎么傳遞到開發工具的呢?
網頁的消息怎么傳遞到開發者工具?
顯而易見,其實就是通過后台頁面作為橋,將內容腳本的消息傳遞到開發者工具中。具體代碼如下:
background.js
// 作為content script 與 devtool 通信的橋
const connections = {};
chrome.runtime.onConnect.addListener(function (port) {
const extensionListener = function (message, sender, sendResponse) {
if (message.name == 'original') {
connections[message.tabId] = port;
}
};
port.onMessage.addListener(extensionListener);
port.onDisconnect.addListener(function(port) {
port.onMessage.removeListener(extensionListener);
const tabs = Object.keys(connections);
for (let i = 0, len = tabs.length; i < len; i++) {
if (connections[tabs[i]] == port) {
delete connections[tabs[i]];
break;
}
}
});
});
// 接收內容腳本的消息,並發送到devtool的消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (sender.tab) {
const tabId = sender.tab.id;
if (tabId in connections) {
connections[tabId].postMessage(message);
} else {
console.log("Tab not found in connection list.");
}
} else {
console.log("sender.tab not defined.");
}
return true;
});
復制代碼
以上,就完成了網頁的消息傳遞到開發者工具的過程,那么開發者工具的消息怎么傳遞到網頁?
開發者工具的消息怎么傳遞到網頁?
開發者工具的消息傳遞到網頁主要有兩種方法:
1、直接使用chrome.devtools.inspectedWindow.eval()方法,在網頁的上下文中執行js代碼,如下:
devtool.js
chrome.devtools.inspectedWindow.eval('console.log(window)');
復制代碼
2、開發者工具通過長連接將消息傳遞到后台頁面,在后台頁面中,通過調用chrome.tab.excuteScript()方法,在網頁中執行js代碼,如下:
background.js
chrome.tab.excuteScript(tabId, {
code: 'console.log(window)'
});
復制代碼
推薦使用第一種方法~
以上,就介紹了網頁與開發者工具之間的通信全過程啦~~~
以上通信方式在文章一開始提到的工具都用到了,倉庫:github.com/HuJiaoHJ/ec…,其實也基本涵蓋了 chrome 開發者工具的所有通信方式~
作者:清爽大錠哥
鏈接:https://juejin.cn/post/6844903651626975245
來源:稀土掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
