popup就是弹出层的页面,一般是用于插件的配置
- popup.html只能引用扩展包内的本地文件,不能用远程地址,默认不能内嵌脚本,内联事件
- 网络请求需要在 manifest.json 中配置
host_permissions权限 - 生命周期短,只有点击扩展图标时,popup 才会加载,点击其他地方,popup 会立即销毁,所以不要在 popup 中写长时任务(比如定时器、轮询),销毁后会直接停止,这类逻辑要放到service worker中
- popup 只能操作自己的 DOM,无法直接操作当前网页的 DOM(需要通过
content script实现)
如果要看popup的打印,需要右击弹出框,然后点检查
popup.html配置
这里面就是标准的html
如果要使用vue,jquery这些, 必须把这些js文件,下载到本地,然后引入
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>popup</title>
<script src="popup/jquery.js"></script>
</head>
<body style="width: 200px">
<script src="popup/popup.js"></script>
</body>
</html>
但是使用vue的话,要麻烦一点
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>popup</title>
</head>
<body style="width: 200px">
<div id="app"></div>
<script type="module" src="popup/vue.global.js"></script>
<script type="module" src="popup/popup.js"></script>
</body>
</html>
import { createApp, h, ref } from './vue.global.js';
// 用 h() 函数创建组件(避免运行时编译模板)
const App = {
setup() {
// 响应式数据(Composition API)
const title = ref("Vue 插件 Popup (V3 安全版)");
const count = ref(0);
const increment = () => {
count.value++;
};
// 返回渲染函数(核心:预编译,无模板编译)
return () => h('div', [
h('h3', title.value),
h('p', `计数:${count.value}`),
h('button', { onClick: increment }, '点击+1')
]);
}
};
// 挂载应用
createApp(App).mount('#app');
一般来说,popup就是一个配置页面,也不会有特别复杂的配置页面,如果有的,一是可以用vite脚手架开发,二是在专门的配置页面去开发
options页面
在manifest.json中配置
"options_ui": {
"page": "hello.html",
"open_in_tab": true
},
右键插件图标,点击选项就可以进到options页面了
如果要实现点击浏览器插件图标,跳转到options页面这个操作,需要在service worker里面实现
一是配置minifest.json中要有action配置
"action": {
"default_icon": {
"16": "icon.png",
"32": "icon.png",
"48": "icon.png",
"64": "icon.png",
"128": "icon.png"
}
},
然后在background.js中监听插件图标的点击事件
// 监听插件图标的点击事件
chrome.action.onClicked.addListener(() => {
// 打开插件的options页面
chrome.runtime.openOptionsPage().catch((error) => {
// 异常处理:如果openOptionsPage失败,手动拼接URL打开
console.error('打开选项页面失败:', error);
const optionsUrl = chrome.runtime.getURL('options/options.html');
chrome.tabs.create({ url: optionsUrl });
});
});
openOptionsPage() 是打开插件配置的options页面,也可以用chrome.runtime.getURL获取插件本地html的路径,然后用chrome.tabs.create去打开
popup通信
与content script通信
有的时候我们需要实现,点击popup的时候,再去执行content script
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', () => {
const sendBtn = document.getElementById('btn1');
sendBtn.addEventListener('click', async () => {
try {
// 1. 获取当前激活的标签页(需要tabs权限)
const [activeTab] = await chrome.tabs.query({
active: true,
currentWindow: true
});
if (!activeTab.id) {
console.warn("无法获取当前标签页ID")
return;
}
// 2. 向content script发送消息
const response = await chrome.tabs.sendMessage(activeTab.id, {
type: 'POPUP_MESSAGE',
data: '这是来自Popup的消息',
timestamp: new Date().getTime()
});
// 3. 接收content script的响应并提示
console.log(`Content Script响应:${response.message}`)
} catch (error) {
// 常见错误:当前页面没有注入content script
console.error(`Content Script响应:${error.message}`)
}
});
});
content script监听消息
// 监听来自Popup的消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('收到来自Popup的消息:', message);
// 判断消息类型并处理
if (message.type === 'POPUP_MESSAGE') {
// 模拟处理逻辑
const replyMessage = `已收到消息:${message.data},当前页面标题是「${document.title}」`;
// 向Popup发送响应(sendResponse必须同步调用,异步需返回true)
sendResponse({
success: true,
message: replyMessage
});
}
// 如果需要异步处理,需返回true(比如调用API后再回复)
// return true;
});
与service worker通信
直接用chrome.runtime.sendMessage发消息就行
const sendBtn2 = document.getElementById('btn2');
sendBtn2.addEventListener('click', async () => {
try {
// 2. 向content script发送消息
const response = await chrome.runtime.sendMessage( {
type: 'POPUP_MESSAGE',
data: {
message: '你好,Service Worker!',
time: new Date().toLocaleTimeString()
}
});
// 3. 接收content script的响应并提示
console.log("Service worker 响应", response)
} catch (error) {
// 常见错误:当前页面没有注入content script
console.error("Service worker 响应失败", error)
}
});
background使用chrome.runtime.onMessage.addListener去接收消息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('Service Worker收到消息:', message);
// 判断消息类型,处理不同逻辑
if (message.type === 'POPUP_MESSAGE') {
// 模拟处理逻辑(比如读取插件存储、调用API等)
const replyContent = `已收到你的消息「${message.data.message}」,时间:${message.data.time}`;
// 向popup发送响应(同步回复)
sendResponse({
success: true,
reply: replyContent
});
}
})