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:暴力枚举每个人获…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
