最近學習了Chrome插件的開發,總體來說上手還是很容易的,因為瀏覽器插件本質上依舊是網頁,寫幾個demo基本就了解了他的開發過程。
什么是Chrome插件
正如開頭所說的,Chrome插件實際上就是一個網頁,由HTML、CSS、JS、圖片等資源組成,與網頁不同的是,Chrome插件是用來增強瀏覽器功能的,同時它還有一套屬於自己的開發規則和API。
每個插件都由不同的組件構成,這些組件大都包括background scripts,content scripts,options page,UI以及各種邏輯文件,當然,這些文件是否需要是根據插件的功能所決定的。
接下來我將通過開發一個獲取頁面圖片並保存的插件來介紹如何開發一個Chrome插件。
獲取頁面上的圖片
首先,我們需要一個目錄來存放這個插件的各個文件。
創建manifest
manifest.json
是一個Chrome插件必不可少的文件,它包含了你插件的所有信息。
{
"name": "獲取圖片",
"description": "獲取頁面上的所有圖片",
"version": "1.0",
"manifest_version": 3
}
只要在目錄中包含manifest.json
,這個目錄就可以被作為一個Chrome插件添加到Chrome當中。
- 在瀏覽器地址欄中輸入
chrome://extensions
,回車以打開瀏覽器的擴展程序界面 - 打開開發人員模式
- 點擊
加載已解壓的擴展程序
,選擇manifest文件所在的目錄
這樣我們就成功安裝了一個擴展,接下來我們要在此基礎上完善它。
用戶界面
一個插件可以有多種形式的用戶界面,這里我們選擇彈出層作為用戶界面,在插件根目錄下創建一個popup.html
,這個頁面需要包含兩個按鈕分別用來觸發獲取圖片和保存圖片的事件,以及一個用來展示圖片的盒子。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
body,
img {
width: 400px;
}
</style>
</head>
<body>
<button id="get">獲取</button>
<button id="save">保存</button>
<div id="app"></div>
</body>
</html>
注意,如果在popup.html
中有中文出現,一定要在head標簽中添加<meta charset="UTF-8" />
,以防止出現亂碼。
創建完成后,我們需要在manifest.json
中聲明該頁面,以保證瀏覽器能夠正確的讀取到它。添加一個action
對象,同時將popup.html
設置為該對象的default_popup
。
{
"name": "獲取圖片",
"description": "獲取頁面上的所有圖片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
},
}
為了讓我們的插件像個正經的插件,給他添加上圖標。我們需要准備16x16、32x32、48x48以及128x128四種大小的圖標圖片,將它們放到目錄中,之后將它們的路徑寫入manifest.json
中。
{
"name": "獲取圖片",
"description": "獲取頁面上的所有圖片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
}
為了讓圖標能夠在擴展程序管理頁面顯示,我們還需要添加一個icons
對象。
{
"name": "獲取圖片",
"description": "獲取頁面上的所有圖片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
"icons": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
}
點擊擴展程序管理頁面中的更新按鈕,即可看到添加完用戶界面的插件信息了。
功能邏輯
之后我們要為插件添加它應有的功能——獲取頁面圖片。
首先我們先簡單梳理一下需求:
- 點擊popup.html中的獲取按鈕,拿到當前頁面的圖片
- 點擊popup.html中的保存按鈕,將拿到的圖片保存下來
實際上我們的插件與當前正在活動的頁面並不是同一個頁面,因此我們需要通過某種方式來將獲取圖片的js代碼發送到當前活動頁上,並且還需要這段js代碼能夠在獲取到圖片之后將圖片發送到popup.html
中。
這里我們就需要用到一開始提到的content scripts組件以及content script與popup之間通信的API。content scripts簡單來說就是插入頁面的腳本,雖說是插入頁面的腳本,實際上它與頁面原本的js是分割開的,雙方不能獲取到對方的變量、函數等內容。不過content scripts還是可以獲取到dom的。
獲取圖片
首先添加一個content-script.js
,這個腳本主要有兩個功能,一是獲取圖片,二是監聽popup傳來的消息,然后將獲取到的圖片作為回信傳回去。
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// message的數據格式取決於發送時的數據
const { start } = message;
if (start) {
const images = document.getElementsByTagName('img');
const imgSrcList = Array.from(images).map((img) => img.src);
sendResponse(imgSrcList);
}
});
之后我們要在manifest.json
中聲明配置它
{
...
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"js/content-script.js"
]
}
]
}
matches
聲明了content scripts要注入的頁面,<all_urls>
表示所有頁面,js
屬性聲明了要注入的js腳本,除此之外還有css
屬性聲明要注入的css代碼、run_at
屬性聲明注入時機等都可以在官方文檔中找到。
之后添加一個popup.js
為界面上的按鈕注冊點擊事件,並在popup.html
中引入它
let srcList;
const getImageBtn = document.getElementById('get');
getImageBtn.addEventListener('click', async () => {
// 獲取當前活動頁
chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
let message = { start: true };
// 向content scripts發送消息
chrome.tabs.sendMessage(tab.id, message, (res) => {
srcList = Array.from(new Set(res));
// popup中展示圖片
const imgList = srcList.map((src) => `<img src="${src}" />`).join('');
document.getElementById('app').innerHTML = imgList;
});
});
});
const saveImageBtn = document.getElementById('save');
saveImageBtn.addEventListener('click', () => {
// 保存圖片
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
body,
img {
width: 400px;
}
</style>
</head>
<body>
<button id="get">獲取</button>
<button id="save">保存</button>
<div id="app"></div>
<script src="./js/popup.js"></script>
</body>
</html>
這里我們需要注意,插件要想和當前活動頁面通信就需要首先獲取它的tabId,而要獲取當前活動頁面的tabId則需要給予插件對應的權限,因此我們需要在manifest.json
中聲明所需要的權限。
{
...
"permissions": [
"activeTab"
]
}
完成后更新一下插件,然后打開想要獲取圖片的頁面點擊獲取按鈕即可(如果頁面已經提前打開請刷新一下)
保存圖片
js可以通過a標簽設置href和download屬性來實現批量保存圖片,但是這里我們要通過調用chrome的download API來實現。
...
saveImageBtn.addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
if (!srcList) {
document.getElementById('app').innerHTML = '未獲取圖片';
return;
}
srcList.forEach((src) => {
chrome.downloads.download({
url: src,
});
});
});
});
與獲取活動頁面相同,download API同樣也需要獲取權限
{
...
"permissions": [
"activeTab",
"downloads"
]
}
這樣一個獲取當前頁面圖片的插件就完成了。