chrome V3 插件开发 基础
目录
- 准备
- popup
- 通信
- popup 发消息给 background
- popup 发消息给 content
- 长期连接
- 如何页面上添加一个按钮?
- tabs.onUpdated
- content-script.js
- inject.js
- 右键菜单
- chrome.contextMenus
- 举个例子添加
- 关于报错(cannot create item with duplicate id XXX)
小白学习chrome 插件开发,如果有什么不对的,请指教
注意: 用的是 chrome V3
准备
- 创建文件夹
myPlugin - 在
myPlugin文件中创建manifest.json文件 - 在
myPlugin文件中创建icons文件文件夹,并且在icons文件中准备一个图片

- 配置
manifest.json
更多参数配置可以查看官网:Manifest file format
{"name": "插件","version": "1.0","manifest_version": 3,"description": "学习chrome插件开发","author": "chenss","icons": {"16": "icons/logo.png","48": "icons/logo.png", "128": "icons/logo.png"}
}
- 打开
管理扩展插件,把myPlugin添加进来就能看到了,如果图标不正确可以点击刷新,如果还不行请检查配置路径


准备工作就到这里了,如果你一切顺利,我们继续吧~
popup
创建 popup.html 和 popup.js
popup.html
<!DOCTYPE html>
<head><meta charset="utf-8" /><body><div>chenss</div></body>
</head>
配置 manifest.json
...
"action": {"default_popup": "popup.html"
}
点击插件,就能弹出一个弹框啦~~~

通信
简单通信使用 runtime.sendMessage() 和 tabs.sendMessage()发消息,在接收端使用 runtime.onMessage 来接收消息。
在根目录新建content-script.js,配置 manifest.json
...
"action": {"default_popup": "popup.html"
},
"content_scripts": [{"matches": ["*://*/*","<all_urls>"],"js": ["content-script.js"]}
],
"permissions": ["tabs"]
popup 发消息给 background
在 popup.html 添加按钮
<div><div class="box"><button id="backgroud">给bg发消息</button></div><script src="popup.js"></script>
</div>
popup 和 background 分别添加如下代码
// popup.js
let sendBg = document.getElementById("backgroud");
sendBg.onclick = async function () {const [tab] = await chrome.tabs.query({active:true,currentWindow:true})console.log('p->b,tab',tab)const respone =await chrome.runtime.sendMessage(tab.id)console.log('popup-respone',respone);
}
// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {console.log('这是background脚本onMessage', message);sendResponse("收到消息");
});
接下来我们看看效果:
点开这个地方

当然 你也可以使用 chrome.runtime.sendMessage 发消息
// popup.js
let sendBg = document.getElementById("backgroud");
sendBg.onclick = async function () {chrome.runtime.sendMessage({greeting:"hello"}, function(response) {console.log(response);
}
popup 发消息给 content
- 同样在
popup.html添加按钮 popup和background分别添加如下代码
// popup.js
let sendContent = document.getElementById("sendContent");
sendContent.onclick = async function () {const [tab] = await chrome.tabs.query({active:true,currentWindow:true})console.log('p->b,tab',tab)const respone =await chrome.tabs.sendMessage(tab.id, {greeting: "hihihihihi"})console.log('popup-respone',respone);
}
// content-script.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {console.log('这是content-script脚本执行内容');console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");}
);
随便打开一个网站 你就能看到 输出内容

简单通信就不再这里过多描述了,可以参考这个文章:
Chrome插件:浏览器后台与页面间通信
长期连接
有的时候需要长时间通信,以上方法显然不合适。需要使用 runtime.connect 或 tabs.connect。
建立连接时,两端都将获得一个 runtime.Port 对象,用来通过建立的连接发送和接收消息。
更多详细内容可以看文档,本次只用runtime.connect举列子。
- 同样在
popup.html添加按钮 popup和background分别添加如下代码
// popup.js
// 长期链接 发消息给bg
longLink.onclick = async function () {var port = chrome.runtime.connect({ name: "knockknock" });port.postMessage({ joke: "Knock knock" });port.onMessage.addListener(function (msg) {if (msg.question === "Who's there?") port.postMessage({ answer: "Madame" });else if (msg.question === "Madame who?")port.postMessage({ answer: "Madame... Bovary" });});
};
// background.js
chrome.runtime.onConnect.addListener(function(port) {console.assert(port.name === "knockknock");port.onMessage.addListener(function(msg) {console.log('msg',msg);if (msg.joke === "Knock knock")port.postMessage({question: "Who's there?"});else if (msg.answer === "Madame")port.postMessage({question: "Madame who?"});else if (msg.answer === "Madame... Bovary")port.postMessage({question: "I don't get it."});});
});
当从 service worker 向 content scripts 发送建立连接请求时,若目标 tab 中存在多个 iframe ,且 content scripts 注入到了每个 iframe 中,则每个 iframe 中的 runtime.onConnect 事件都会被触发。同样的,也可能会出现多个 iframe 中的runtime.connect() 一起调用的情况。
如何页面上添加一个按钮?
tabs.onUpdated
使用 tabs.onUpdated , 再次强调一下需要配置permissions: [‘tabs’],并且需要重新加载插件,如重新加载还是无法生效,请移除插件重新导入
在background.js 代码如下:
//background.js
chrome.tabs.onUpdated.addListener(async function(tabId,changeInfo,tab){console.log('tabs.onUpdated',tabId,changeInfo,tab);if (!tab.url &&changeInfo.status !=='complete') return;sendContent(tabId,{action:"inject"})
});
content-script.js
// content-script.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {var tmp = document.createElement("script");tmp.src = chrome.runtime.getURL("./inject.js");tmp.setAttribute("type", "text/javaScript");document.head.appendChild(tmp);
});
inject.js
manifest.json 中配置
"web_accessible_resources": [ {"resources": ["inject.js"],"matches": [ "*://*/*" ]}],
“matches”:字符串数组,每个字符串都包含一个匹配模式,指定哪些站点可以访问这组资源。仅使用来源来匹配 URL。例如"matches": [ "http://*/*" ] 这样配置的话,https开头网址的页面上看不到按钮。当然可以利用正则匹配网页地址。
//inject.js
var div_child='<button id="div_child_1" style="width:100px;height:50px;position: absolute;top: 120px;right: 50px;font-size: 24px;">按钮</button>'
var c=document.querySelector("body > div");
c.innerHTML+=div_child;let injectBtn = document.getElementById("div_child_1");
injectBtn.onclick= function(){alert("点击了自定义的按钮")
}

右键菜单
chrome.contextMenus
chrome.contextMenus 文档地址
举个例子添加
background.js 里面添加如下代码
//background.js
chrome.runtime.onInstalled.addListener(() => {createMenus()
});
// 自定义右键菜单
function createMenus() {chrome.contextMenus.create({title: "菜单1", //菜单的名称id: '01', //一级菜单的idcontexts: ['page'], // page表示页面右键就会有这个菜单,如果想要当选中文字时才会出现此右键菜单,用:selection});chrome.contextMenus.create({title: '子菜单1', //菜单的名称id: '0101',//二级菜单的idparentId: '01',//表示父菜单是“右键快捷菜单”contexts: ['page'],});chrome.contextMenus.create({title: '菜单2', //菜单的名称id: '02',contexts: ['page'],});}
这样就添加成功了
关于报错(cannot create item with duplicate id XXX)
例如:一开始的时候在onUpdated 周期添加菜单
chrome.tabs.onUpdated.addListener(async function(tabId,changeInfo,tab){chrome.contextMenus.create({...})
});
每次刷新页面的时候就会出现这个重复添加的错误:
是因为 onUpdated 状态是loading 和 complate 的时候重复添加了,当然可以判断一下加载状态,再去创建。
如果你通过通信方式添加菜单也需要注意,也会存在这个问题。

关于这个文档里有说(使用此事件(onInstalled)可以设置状态或进行一次性初始化,例如上下文菜单。):

未完待续👻👻👻👻👻👻👻👻
相关文章:
chrome V3 插件开发 基础
目录 准备popup通信popup 发消息给 backgroundpopup 发消息给 content长期连接 如何页面上添加一个按钮?tabs.onUpdatedcontent-script.jsinject.js 右键菜单chrome.contextMenus举个例子添加关于报错(cannot create item with duplicate id XXX…...
【uniapp】uniapp自动导入自定义组件和设置分包:
文章目录 一、自动导入自定义组件:二、设置分包和预加载: 一、自动导入自定义组件: 【Volar 官网】https://github.com/vuejs/language-tools 二、设置分包和预加载: 【官方文档】https://uniapp.dcloud.net.cn/collocation…...
【深度学习MOT videos detect】Detect to Track and Track to Detect
论文:https://arxiv.org/abs/1710.03958 代码:https://github.com/feichtenhofer/Detect-Track 文章目录 Abstract1. Introduction2. Related work后面翻译略 Abstract 近期用于在视频中高精度检测和跟踪目标类别的方法越来越复杂,每年都变得…...
关于Neo4j的使用及其基本命令
关于Neo4j的使用 文章目录 关于Neo4j的使用1、启动方式2、创建新节点,节点内有属性3、创建关系4、查询节点5、查询关系6、删除两个节点的关系7、删除节点8、删除某个标签的全部关系9、某个节点添加属性10、删除节点某个属性 1、启动方式 进入bin目录: …...
【笔记】树状数组
【笔记】树状数组 目录 简介引入1. 直接暴力2. 维护前缀和数组总结 定义前置知识: lowbit \operatorname{lowbit} lowbit 操作区间的表示方法操作单点修改前缀和查询任意区间查询 例题1: 单点修改,区间查询例题2: 区间修改,单点查询例题3:…...
vue全局组件自动注册直接使用,无需单独先引用注册再使用
目录结构: 本案例是在根目录下components文件夹测试的,文件位置项目内任意,确保在main.js挂载路径正确即可 1、新建文件夹(名字随意)zxy_components (放自己组件的地方) 2、在zxy_components文件夹下 !新建…...
【HarmonyOS】@ohos.request 上传下载的那些事儿
【关键字】 ohos.request、上传下载 【写在前面】 在进行HarmonyOS应用开发时,可能需要进行上传或下载文件功能开发,本文章主要进行上传下载相关功能介绍和一些注意事项及FAQ。 【上传开发步骤】 步骤1:上传下载接口需要申请ohos.permis…...
github版面混乱加载不出的解决办法
最近出现打开github 界面加载不成功,网页访问乱码,打开chrome的检查发现 github的github.githubassets.com 拒绝访问, 解法: 1.先打开hosts文件所在的目录C:\Windows\System32\drivers\etc 2.右键点击hosts文件-选择用记事本或者…...
dotNet 之数据库sqlite
Sqlite3是个特别好的本地数据库,体积小,无需安装,是写小控制台程序最佳数据库。NET Core是同样也是.NET 未来的方向。 **硬件支持型号 点击 查看 硬件支持 详情** DTU701 产品详情 DTU702 产品详情 DTU801 产品详情 DTU802 产品详情 D…...
走近ChatGPT与类似产品:原理解析与比较
目录 1. 引言1.1 技术的进步与自然语言处理1.2 ChatGPT的崭新概念 2. ChatGPT: 一览众山小2.1 GPT-3.5架构简介2.2 ChatGPT的学习与训练2.3 文本生成的工作原理 3. 市场上类似产品调研3.1 对话式人工智能产品分类3.2 文心一言3.3 讯飞星火 4. 应用前景与局限性展望4.1 ChatGPT的…...
HarmonyOS SDK开放能力,服务鸿蒙生态建设,打造优质应用体验
华为开发者大会2023(HDC.Together)于8月4日至6日在东莞松山湖举行,在HarmonyOS端云开放能力技术分论坛上,华为为广大开发者们介绍了HarmonyOS SDK开放能力在基础开发架构、功能特性等方面的变化之处,通过将常见的通用能…...
数字经济对产业结构升级和创业增长的影响(2011-2021年)
参照刘翠花(2022)的做法,对来自中国人口科学《数字经济对产业结构升级和创业增长的影响》一文中的基准回归部分进行复刻。文章从理论层面分析数字经济发展对产业结构升级、创业增长的影响及其机理,并利用2011-2021年中国省级面板数…...
GPT-4助力数据分析:提升效率与洞察力的未来关键技术 | 京东云技术团队
摘要 随着大数据时代的到来,数据分析已经成为企业和组织的核心竞争力。然而,传统的数据分析方法往往无法满足日益增长的数据分析需求的数量和复杂性。在这种背景下,ChatGPT-4作为一种先进的自然语言处理技术,为数据分析带来了革命…...
Zabbix6 对接飞书告警
文章目录 Zabbix对接飞书告警背景创建飞书群组Zabbix配置创建告警媒介类型创建动作用户关联飞书告警 Zabbix对接飞书告警 背景 运维 你看下他的进程是不是挂了,之前在9点28分有发消息的,这次没有发消息 哐哐哐的去看了一通,确实有个进程之前…...
Javascript异步编程的4种方法
你可能知道,Javascript语言的执行环境是"单线程"(single thread)。 所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一…...
【MySQL】表的内外连接
目录 一、内连接 二、外连接 1、左外连接 2、右外连接 一、内连接 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。 语法: select 字段 from 表1 i…...
详解Mysql——第一篇/连接查询
mysql的连接查询,相必在网上都能找到很多的教程,博主今天不做老话常谈,不走重复路线 1.建表 –1.学生表 Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_id) – –课程编…...
uniapp获取屏幕宽度时 获取不到移动设备中内容盒子宽度
首先 :我使用的是uniapp vue3语法: 问题: 我出现这个问题是IOS 设备发现的,data.boxWidth为0 代码: const initCreated () > {const query uni.createSelectorQuery().in(instance.proxy);const el query.select…...
篇十二:代理模式:控制对象访问
篇十二:“代理模式:控制对象访问” 开始本篇文章之前先推荐一个好用的学习工具,AIRIght,借助于AI助手工具,学习事半功倍。欢迎访问:http://airight.fun/。 另外有2本不错的关于设计模式的资料,…...
P1657 选书
1:思路:一看数据,嗯....!,爆搜嘛?,看一眼题目,嗯!!!,爆搜! 配上俺的无敌小剪枝,按下拿下! 2:暴力枚举每个人获…...
避坑指南:PyTorch中ReflectionPad2d和ReplicationPad2d用错了?详解两者区别与适用场景
PyTorch边界填充终极指南:ReflectionPad2d与ReplicationPad2d的深度抉择 在图像处理任务中,边界填充(Padding)是一个看似简单却影响深远的关键操作。许多开发者在实现卷积神经网络时,往往只关注模型架构和损失函数的设…...
Z-Image-GGUF提示词入门:‘主体+风格+光照+质量’四步法详解
Z-Image-GGUF提示词入门:‘主体风格光照质量’四步法详解 你是不是也遇到过这种情况:看到别人用AI生成的图片惊艳无比,自己上手一试,出来的却总是不尽人意?要么是画面模糊,要么是风格跑偏,要么…...
抖音批量下载器:5分钟打造你的专属素材库
抖音批量下载器:5分钟打造你的专属素材库 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. 抖音批量…...
移动端模型瘦身实战:如何用MobileNet的深度可分离卷积,把ResNet18压缩到5MB以下(附TensorFlow Lite部署代码)
移动端模型瘦身实战:深度可分离卷积在ResNet18压缩中的应用 当你在开发一款需要实时图像识别的移动应用时,是否曾被模型体积过大所困扰?一个标准的ResNet18模型动辄40MB以上,这对于移动端应用来说简直是灾难。但通过深度可分离卷积…...
3个步骤轻松获取百度网盘真实下载地址:告别龟速下载的完整指南
3个步骤轻松获取百度网盘真实下载地址:告别龟速下载的完整指南 【免费下载链接】baidu-wangpan-parse 获取百度网盘分享文件的下载地址 项目地址: https://gitcode.com/gh_mirrors/ba/baidu-wangpan-parse 你是否经常遇到百度网盘下载速度只有100KB/s的困扰&…...
第30篇:AI辅助法律与合同审查——降低中小企业风险的成本利器(项目实战)
文章目录项目背景技术选型架构设计核心实现踩坑记录效果对比项目背景 在上一轮创业时,我吃过合同的亏。一份看似标准的采购协议,因为一个模糊的“验收标准”条款,导致交付后与供应商扯皮了近三个月,最终以我们承担额外成本告终。…...
股市学习心得-PCB 核心原材料
PCB ( 印制电路板)-核心原材料(所提供内容仅用于学习,不作为股市交易依据)印制电路板(PCB)上游产业链核心分为核心原材料和生产设备两大板块,是PCB产业发展的基石,直接决定我国PCB产业的全球竞争…...
我的停车场项目翻车了:MaixCAM车牌识别中的串口通信与数据滤波避坑指南
MaixCAM车牌识别实战:从数据抖动到稳定通信的工程化解决方案 停车场闸机突然放行了一辆错误车辆,而正确识别的车牌却在系统里重复计费三次——这是我在最近一个智能停车场项目中遇到的真实灾难。当MaixCAM作为视觉协处理器与主控单片机通信时,…...
从SiamFC到SiamRPN++:一个PyTorch复现者的五年跟踪算法演进笔记
从SiamFC到SiamRPN:一个PyTorch复现者的五年跟踪算法演进笔记 1. 初识SiamFC:全卷积孪生网络的革命性突破 2016年首次接触SiamFC时,它的设计理念让我眼前一亮。传统目标跟踪算法通常需要在每一帧进行复杂的在线学习,而SiamFC却另辟…...
hermes agent 初体验
一、安装 参考链接:https://dashscope.aliyuncs.com/compatible-mode 二、报错及解决 问题1:WSL2安装报错 我是WSL2安装的,期间报错:Failed to install uv。我并没有按照他的要求手动去安装,而是再次执行:c…...
