在我們平時的開發工作中,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 開發者工具的所有通訊方式~
寫在最後
學習了 chrome devtools 的通訊方式之後,就能愉快的開發自己的開發者工具啦,希望能對有需要的小夥伴有幫助~~~
喜歡我的文章小夥伴可以去 我的個人部落格 點star ⭐️