# Chrome插件使用
Chrome插件就是一个简单HTML静态文件,和正常的网页开发一样,遵循插件的格式和使用对应的API就可以了。并且可以支持向服务端发送请求。插件的几个核心点就是弹窗、内容脚本、Service Worker线程服务,还有这几个插件之间互相发送和接收消息。
# 创建项目
Chrome插件项目就是普通的HTML页面,就多了一个manifest.json配置文件,项目创建好直接在浏览器中导入就可以用了。
├── background # Service Worker文件
│ └── background.js
├── images # 图片
├── popup # 插件弹窗文件
│ ├── popup.html # 弹窗html
│ ├── popup.css # 弹窗css
│ └── popup.js # 弹窗js
├── scripts # 内容脚本
│ ├── query.min.js # 其他js文件
│ └── content.js # 内容脚本
├── manifest.json # 配置文件
# 安装
项目创建好后在新标签页中输入 chrome://extensions,转到“扩展程序”页面。右侧打开 开发者模式 会有几个按钮。点击 加载已解压的扩展程序 按钮,选择对应的文件就会把插件加载到浏览器中。
然后把插件固定到右上角的插件栏,点击就可以执行插件了。
# 配置文件
manifest.json文件用来描述插件和配置插件使用哪些功能。相当于入口文件。
action 配置插件的图片和弹窗内容
content_scripts 配置插件的内容脚本
background 配置插件的Service Worker
// manifest.json
{
"manifest_version": 3,
"name": "Hello Extensions of the world!",
"description": "Base Level Extension",
"version": "1.0",
"icons": {
"16": "images/icon-16.png",
"32": "images/icon-32.png",
"48": "images/icon-48.png",
"128": "images/icon-128.png"
},
"action": {
"default_popup": "popup/hello.html"
},
"background": {
"service_worker": "background/background.js"
},
"content_scripts": [
{
"js": ["scripts/content.js"],
"matches": [
"https://developer.chrome.com/*"
]
}
]
}
# 弹窗
popup为插件的弹窗内容,弹窗相当于一个单独的浏览器页面,可以在这个窗口进行界面开发,和我们正常的HTML、JS、CSS一样使用。审查该弹窗元素需要打开弹窗,右击点击检查。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./popup.css">
</head>
<body>
<div class="index">
<div class="index-header">
<h1>1Hello Extensions</h1>
</div>
<div class="index-btn">
<button id="start-btn1">向Content发送消息</button>
</div>
<div class="index-btn">
<button id="start-btn2">向Service Worker发送消息</button>
</div>
</div>
<script src="./popup.js"></script>
</body>
</html>
// popup.js
// 插件弹窗JS内容,右键弹窗审查会审查弹窗的DOM内容,而不是网页的
console.log("This is a popup!");
var startBtn1 = document.getElementById('start-btn1');
var startBtn2 = document.getElementById('start-btn2');
startBtn1.addEventListener('click', function() {
console.log('点击按钮1');
sendMessageToContent('startContentMsg', function(response) {
console.log('向Content发送消息成功', response);
})
})
startBtn2.addEventListener('click', function() {
console.log('点击按钮2');
sendMessageToServiceWorker('startServiceWorkerMsg', function(response) {
console.log('向ServiceWorker发送消息成功', response);
})
})
/**
* @desc 向内容脚本发送消息
* @param action 消息类型
* */
function sendMessageToContent(action, callback) {
chrome.tabs.query({active: true}, function(tabs) {
const tab = tabs[0];
chrome.tabs.sendMessage(tab.id, { action: action }, callback);
});
}
/**
* @desc 向Service Worker 发送消息
* @param action 消息类型
* */
function sendMessageToServiceWorker(action, callback) {
chrome.runtime.sendMessage({ action: action }, callback);
}
# 内容脚本
用来处理插件所在网页相关的JS内容,比如获取页面中的DOM元素、页面内容、手动触发按钮、模拟操作DOM等,除了接口无法获取,其他操作 都可以像在网页的js中一样执行。
它无法直接处理popup内容。调试可以直接在所在网页中进行调试。
// content.js
// 执行内容脚本,针对的是使用插件的网页,审查也是使用的页面审查元素
console.log('This is a content!')
// 获取页面的元素
console.log(document)
// 发送消息给service worker
function sendMessageToServiceWorker(action, params, callback) {
chrome.runtime.sendMessage({ action: action, params: params}, callback);
}
// 修改背景颜色
function changeBodyBg() {
const body = document.querySelector('body');
console.log(body);
body.style.background = 'red';
}
// 向Service Worker发送消息
function getReplyMessage() {
sendMessageToServiceWorker('getReplyMessage', '我是content消息', function(response) {
console.log('获取Service Worker的接口数据:', response)
})
}
// 定义一个对象,用于映射 action 到相应的处理函数
const actionHandlers = {
startContentMsg: function (message, sendResponse) {
changeBodyBg();
getReplyMessage();
sendResponse('返回消息成功');
}
}
// 接收弹窗Popup和Service Worker发送来的消息
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
console.log(message)
// 检查是否有处理该 action 的函数
if (actionHandlers[message.action]) {
// 调用对应的处理函数
actionHandlers[message.action](message, sendResponse);
} else {
console.warn(`未处理的 action: ${message.action}`);
}
// 必须返回 true 以异步响应消息
return true;
})
# Service Worker
只用来处理一些核心线程问题,比如调用接口数据,在其中无法访问DOM元素。
// background.js
console.log("Service worker 已加载");
// 监听插件的安装或更新事件
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
console.log("插件已安装");
// 这里可以执行一些初始化操作,比如设置默认配置
chrome.storage.local.set({ installed: true });
} else if (details.reason === chrome.runtime.OnInstalledReason.UPDATE) {
console.log("插件已更新");
// 这里可以执行一些更新后的操作,比如迁移数据
} else if (details.reason === chrome.runtime.OnInstalledReason.CHROME_UPDATE) {
console.log("Chrome 浏览器已更新");
}
});
// 定义一个对象,用于映射 action 到相应的处理函数
const actionHandlers = {
// 接收Content发送的消息
getReplyMessage: function(message, sendResponse) {
console.log("收到消息Content发送的消息", message);
// 调用API请求
fetch("https://jsonplaceholder.typicode.com/posts", {
method: "GET",
}).then(response => response.json())
.then(res => {
console.log(res)
sendResponse(res)
})
.catch(err => console.log('Request Failed', err));
},
// 接收弹窗发送的消息
startServiceWorkerMsg: function(message, sendResponse) {
console.log('接收弹窗发送的消息', message)
sendResponse('我是ServiceWorker')
}
};
// 监听来自弹窗和Content的消息
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
// 检查是否有处理该 action 的函数
if (actionHandlers[message.action]) {
// 调用对应的处理函数
actionHandlers[message.action](message, sendResponse);
} else {
console.warn(`未处理的 action: ${message.action}`);
}
// 必须返回 true 以异步响应消息
return true;
});
# 发布
发布插件 (opens new window)需要去注册Chrome插件开发者账号,注册好后就可以去发布了。
# 参考示例
官方示例:https://github.com/GoogleChrome/chrome-extensions-samples (opens new window)
github:https://github.com/changzhengithub/chrome-extension (opens new window)
← Markdown语法 VsCode使用技巧 →