寫個自己的 chrome 插件
有沒有好奇 chrome[1] 插件是用什麼做的?像類似掘金
插件又是怎麼實現的,當我安裝稀土掘金插件後,我的導航頁都被改掉了,因此你也可以做一個類似的插件,來導航你公司的一些產品,方便快捷的實現你的內部導航
在開始本文之前,主要是從零認識一個chrome
插件, 主要會從以下幾點去認識chrome插件
-
核心配置
manifest.json
配置,必不可少的幾個配置 -
popup
爲插件內容文件 -
background
與content
通信,popup
與content
通信 -
chrome.runtime
幾個通信API
正文開始...
首先預知的幾個文件
manifest.json
,必須在插件根目錄上新建一個這樣的文件, 我們從官網查看更多的 manifest[2] 信息
{
// 必不可少
"manifest_version": 3, // 擴展插件版本必須是2以上
"name": "Maic_test_chrome", // 擴展名稱
"description": "lesson demo", // 擴展描述
"version": "1.0",
// 可選
"action": {
"default_popup": "popup/index.html", // 默認的頁面
"default_icon": "logo.png" // 瀏覽器擴展插件顯示圖標
},
// 在插件列表裏顯示不同尺寸的圖標
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
}
}
讓當前網頁加載一個腳本
content_scripts
指定加載對應腳本js
,css
注意matches
中匹配的是當前訪問的 url, 當選擇<all_urls>
時,匹配任何 url, 必須要有 matches[3] 否則不會生效
"content_scripts": [
{
"js": [
"scripts/content.js"
],
"matches": [
"https://*.wmcweb.cn/*",
"<all_urls>"
]
}
]
background 增強瀏覽器事件程序的 js
{
"background": {
"service_worker": "background.js"
}
}
background.js
與content.js
通信
background.js
在插件頁面加載,background.js
調用onMessage.addListener
接收content.js
發送過來的數據
function callback(info, curent, sendToContent) {
}
chrome.runtime.onMessage.addListener(callback)
// background.js 在插件頁面加載
const user = {
username: 'Maic'
};
// 調用onMessage.addListenter
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('background.js', message, sender)
// 2. A page requested user data, respond with a copy of `user`
if (message === 'get-user-data') {
sendResponse(user);
}
});
content.js
在你指定的匹配域名頁面加載,與當前瀏覽器加載的頁面同環境
content.js
,content
向background.js
發送信息
chrome.runtime.sendMessage(info, callbackResponse)
// sendMessage content.js
chrome.runtime.sendMessage('get-user-data', (response) => {
console.log('received user data', response);
});
popup.js
向content.js
通信
在popup
頁面需要查找當前激活的tabs
// popup.js
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, {}, function (response) {
console.log(response, 'content.js回傳過來的信息');
});
});
在content.js
接收信息
function callback(request, sender, sendResponse) {}
chrome.runtime.onMessage.addListener(callback)
content.js
詳細代碼參考以下
// content.js
console.log('loader-content')
// 1. content向service worker發送信息
chrome.runtime.sendMessage('get-user-data', (response) => {
// 2,接受service worker回調過來的信息
console.log('received service worker data', response);
});
const render = ({ style, title }) => {
const boxDom = document.querySelector('.box');
const contentDom = document.querySelector('.content');
const resultDom = document.querySelector('.result');
boxDom.style.width = style.width;
boxDom.style.height = style.height;
boxDom.style.backgroundColor = style.backgroundColor;
contentDom.innerText = title;
resultDom.innerText = JSON.stringify({ ...style, title }, null, 2)
}
// 接收popup.js發送過來的信息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('content', request, sender);
const {
inputColorValue,
titleValue,
widthValue,
heightValue } = request;
const style = {
width: `${widthValue}px`,
height: `${heightValue}px`,
backgroundColor: inputColorValue
}
const receivePopupInfo = {
style,
title: titleValue
}
// 向popup.js回傳信息
sendResponse(receivePopupInfo)
render(receivePopupInfo)
});
background.js
參考如下
const user = {
username: 'Web技術學苑'
};
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('background.js', message, sender)
if (message === 'get-user-data') {
sendResponse(user);
}
});
popup.js
參考如下
const $ = id => document.getElementById(id);
function setBadge() {
const inputColorValue = $('color-input').value;
const titleValue = $('title-input').value;
const widthValue = $('width-input').value;
const heightValue = $('height-input').value;
const info = {
inputColorValue,
titleValue,
widthValue,
heightValue
}
chrome.action.setBadgeText({ text: inputColorValue });
// 擴展腳本向content發出信息
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
console.log(tabs)
chrome.tabs.sendMessage(tabs[0].id, info, function (response) {
console.log(response, 'content.js回傳過來的信息');
});
});
}
$('submit').addEventListener('click', setBadge);
['width', 'height'].forEach(dom => {
const curent = $(`${dom}-input`);
curent.addEventListener('change', (evt) => {
$(`${dom}-result`).innerText = evt.target.value;
})
});
我們再看下popup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta />
<title>Document</title>
<link rel="stylesheet" href="popup.css" />
</head>
<body>
<div>
<div>title: <input type="text" value="我是標題" /></div>
<div>color:<input type="color" /></div>
<div>
width: <input type="range" value="30" max="1000" />
<span>30</span>
</div>
<div>
height: <input type="range" value="30" max="1000" />
<span>30</span>
</div>
<button>確定</button>
</div>
<script src="./popup.js"></script>
</body>
</html>
當你打開瀏覽chrome://extensions/
然後添加插件04-demo
在打開一個測試頁面
我通過插件中的popup.js
與content.js
通信,就可以修改我當前頁面上的元素了
另外推薦一個chrome
插件官方的例子 chrome-extensions-samples[4],看完一些例子多插件喲更深刻的認識,在下一節裏,我會利用chrome
內置緩存能力做一些與我們實際業務相關的例子。
總結
-
一個
chrome
插件基礎文件manifest.json
幾個比較的參數,加載插件根目錄必須要有個文件,且manifest_version
是2
版本上 -
popup.js
與content.js
交互,content.js
是獨立於插件外部腳本,當匹配對應網頁時,可以利用content.js
控制當前網頁 -
background.js
是運行插件增強js
, 我們可以在這background.js
控制chrome
插件,或者與popup.js
的通信 -
chrome
核心api
,chrome.runtime.onMessage
,chrome.runtime.sendMessage
,chrome.tab.query
的使用 -
本文示例 code example[5]
參考資料
[1]chrome: https://developer.chrome.com/docs/extensions/mv3/
[2]manifest: https://developer.chrome.com/docs/extensions/mv3/manifest/
[3]matches: https://developer.chrome.com/docs/extensions/mv3/content_scripts/#programmatic
[4]chrome-extensions-samples: https://github.com/GoogleChrome/chrome-extensions-samples
[5]code example: https://github.com/maicFir/lessonNote/tree/master/chrome-plugin/04-demo
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/32YMmbfjAxl2JWcqDXfx0A