)
Chrome 扩展实战使用 chrome.contextMenus API 自定义浏览器右键菜单chrome-extensions-samples 源码解析【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址: https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples导读本文基于 chrome-extensions-samples 仓库中的 api-samples/contextMenus/basic 示例系统讲解 Manifest V3 下chrome.contextMenusAPI 的核心用法如何在浏览器右键菜单中创建菜单项、为不同类型的上下文页面、选区、链接、图片等注册菜单、区分普通 / 单选 / 复选菜单行为并在点击时执行自定义逻辑。读完本文你将掌握一套可直接复制运行的右键菜单扩展骨架并能将控制台演示代码快速改造为真实业务功能。示例概览一个覆盖全部菜单形态的最小扩展contextMenus/basic示例的目标非常明确用最少的代码覆盖chrome.contextMenusAPI 的典型场景。按 README.md 的说明该扩展会创建菜单项并针对不同上下文类型context type分别注册监听不同类型菜单项的点击事件根据用户当前选中内容文本、链接、图片等运行对应代码。整个扩展只有三个文件结构一目了然文件职责manifest.json声明权限、注册 Service Workersample.js全部菜单创建与点击处理逻辑README.md示例说明与运行步骤Manifest 配置最小权限声明manifest.json 是这个示例的关键它展示了使用 contextMenus API 的最小合法配置{ name: Context Menus Sample, description: Uses the chrome.contextMenus API to customize the context menu., version: 0.7, permissions: [contextMenus], background: { service_worker: sample.js }, manifest_version: 3 }这里有两个要点permissions: [contextMenus]—— 使用chrome.contextMenus必须在 manifest 中显式声明contextMenus权限否则 API 调用会失败。这是 MV3 下权限模型的要求示例直接展示了这一最小声明方式。后台逻辑放在 Service Worker 中—— 菜单创建与点击监听都位于后台脚本sample.js因为右键菜单项是全局存在的不依赖任何页面存活。示例刻意没有配置action工具栏图标意味着加载后直接右键即可看到菜单无需先点开弹窗。菜单项创建覆盖全部上下文类型README.md 提到listen for different context menu types being clicked监听不同类型上下文菜单的点击对应的实现位于 sample.js。代码在chrome.runtime.onInstalled回调中一次性为 7 种上下文类型各创建一个测试项chrome.runtime.onInstalled.addListener(function () { // Create one test item for each context type. let contexts [ page, // 页面空白处 selection, // 选中文本 link, // 链接 editable, // 可编辑区域输入框、文本框 image, // 图片 video, // 视频 audio // 音频 ]; for (let i 0; i contexts.length; i) { let context contexts[i]; let title Test context menu item; chrome.contextMenus.create({ title: title, contexts: [context], id: context }); } });这段代码揭示了chrome.contextMenus.create()的常用参数title菜单项显示文本contexts菜单项出现的上下文环境示例覆盖了 7 种常见类型。除上述类型外ContextType还支持all所有环境、frameiframe 内、launcher应用启动器等取值读者可按需选用id菜单项唯一标识用于在onClicked事件中区分是哪个菜单项被点击。需要特别说明的是菜单项的创建集中在chrome.runtime.onInstalled中进行。这是官方推荐模式右键菜单项只需在扩展安装/更新时创建一次无需每次启动都重建而点击响应则通过独立的事件监听器处理。示例将创建与响应彻底分离正是这一最佳实践的示范。父子菜单构建层级结构右键菜单支持多级嵌套。示例在 sample.js 中创建了一个父菜单项和两个子菜单项// Create a parent item and two children. let parent chrome.contextMenus.create({ title: Test parent item, id: parent }); chrome.contextMenus.create({ title: Child 1, parentId: parent, id: child1 }); chrome.contextMenus.create({ title: Child 2, parentId: parent, id: child2 });关键点在于parentId参数子菜单项通过parentId指向父菜单项创建时返回的 ID。chrome.contextMenus.create()会返回新菜单项的 ID将其赋给父项变量后再传给子项即可建立层级。注意父子菜单的创建顺序——必须先创建父项才能引用其 ID。父子结构的典型用途是主菜单下按功能分组多个子动作右键区域更整洁。单选与复选菜单radio / checkbox 类型除普通菜单默认type: normal外chrome.contextMenus.create()还支持两种带状态的菜单类型示例在 sample.js 中同时演示了两者// Create a radio item. chrome.contextMenus.create({ title: radio, type: radio, id: radio }); // Create a checkbox item. chrome.contextMenus.create({ title: checkbox, type: checkbox, id: checkbox });两者的行为差异在点击回调中体现得最清楚见下文genericOnClick的switch分支type: radio同一父级下的多个 radio 项互斥一次只能选中一个。点击回调的info.checked反映当前选中状态type: checkbox每个 checkbox 项独立开关可同时勾选多个。同样通过info.checked读取状态。点击回调中还可用info.wasCheckedMV2 时代的叫法读取点击前的状态用于实现切换语义。radio / checkbox 很适合做设置类菜单例如主题切换、开关某个功能。点击事件分发基于 menuItemId 的 switch 分发示例将所有菜单项的点击事件统一交给一个监听器处理按info.menuItemId分发到不同逻辑见 sample.js// A generic onclick callback function. chrome.contextMenus.onClicked.addListener(genericOnClick); function genericOnClick(info) { switch (info.menuItemId) { case radio: // Radio item function console.log(Radio item clicked. Status:, info.checked); break; case checkbox: // Checkbox item function console.log(Checkbox item clicked. Status:, info.checked); break; default: // Standard context menu item function console.log(Standard context menu item clicked.); } }这是示例的核心交互逻辑与 README.md 中run code based on what the user has selected根据用户选中内容运行代码的描述一一对应chrome.contextMenus.onClicked.addListener(callback)注册全局点击监听任何菜单项被点击都会触发回调参数info携带本次点击的上下文信息info.menuItemId是被点击菜单项的 ID即创建时传入的idinfo.checked是 radio / checkbox 项当前状态此外还可访问info.selectionText选中的文本、info.linkUrl、info.srcUrl、info.pageUrl等字段回调的第二个参数tab携带点击发生时所在标签页的信息可用于配合chrome.tabs等 API。如 README 所述这里的控制台输出console readout可以快速替换为新的函数或 API 调用例如把console.log换成chrome.tabs.create打开新标签、chrome.notifications.create发通知或写入chrome.storage。这种监听器 switch 分发模式是右键菜单扩展的通用骨架。错误处理利用 runtime.lastError 校验创建结果chrome.contextMenus.create()是异步 API若参数非法如引用了不存在的父级 ID错误会通过回调中的chrome.runtime.lastError暴露。示例在 sample.js 中特意制造了一个错误场景来演示检查方法// Intentionally create an invalid item, to show off error checking in the // create callback. chrome.contextMenus.create( { title: Oops, parentId: 999, id: errorItem }, function () { if (chrome.runtime.lastError) { console.log(Got expected error: chrome.runtime.lastError.message); } } );这段代码故意给parentId传入不存在的999从而在回调中触发chrome.runtime.lastError。正确姿势是创建菜单项后立即检查chrome.runtime.lastError存在则记录/处理错误。这在动态创建菜单例如父项被删除后再创建子项的场景下尤其重要可避免静默失败导致菜单不显示。进阶参考从控制台演示到真实业务README.md 明确建议将该示例quickly adapted to use new functions or API calls快速适配为使用新函数或 API 调用。仓库中的 global_context_search 示例就是最好的转型范本展示了从控制台打印升级为真实业务的完整路径1. 用菜单项承载业务选项。其 background.js 在onInstalled时读取一份国家/地区配置locales.js包含com.au、cn、co.jp等 12 个 Google 域名为每个地区创建一个contexts: [selection]的菜单项。2. 在点击回调中执行真实动作。background.js 不再打印日志而是读取item.selectionText作为搜索关键词构造对应国家域名的 Google 搜索 URL并用chrome.tabs.create在相邻位置打开新标签页chrome.contextMenus.onClicked.addListener((item, tab) { const tld item.menuItemId; const url new URL(https://google.${tld}/search); url.searchParams.set(q, item.selectionText); chrome.tabs.create({ url: url.href, index: tab.index 1 }); });3. 动态增删菜单项。其 popup.js 允许用户通过弹窗勾选启用的国家改动写入chrome.storage.sync后台再监听chrome.storage.onChanged对新增项调用chrome.contextMenus.create()、对移除项调用chrome.contextMenus.remove(tld)见 background.js。这补充了 basic 示例未覆盖的动态更新菜单能力。对比可见basic 示例负责把 API 的每一种形态讲透进阶示例则演示了如何把同样的 API 接入真实交互链路。两者结合即构成完整的 contextMenus 学习路径。历史对照MV2 时代的实现差异仓库的 _archive/mv2/api/contextMenus/basic/sample.js 保留了 Manifest V2 版本的同名示例与当前 MV3 版对比可以直观看到 API 演进事件注册方式MV2 版在create()参数中直接传onclick回调如{title:..., onclick: genericOnClick}MV3 版统一改用chrome.contextMenus.onClicked.addListener()事件监听与create()彻底解耦一个监听器服务全部菜单项错误读取位置MV2 版通过chrome.extension.lastError读取错误见 MV2 sample.jsMV3 下该字段迁移为chrome.runtime.lastError后台载体MV2 可用事件页_archive 目录下另有event_page变体MV3 统一为 Service Worker。从源码结构看这一对照恰好解释了为何当前示例将创建onInstalled内create与响应onClicked监听分离——这正是 MV3 推荐的事件驱动写法。运行与验证三步加载扩展按 README.md 的 Running 章节加载并验证该扩展只需三步获取代码git clone本仓库gh_mirrors/ch/chrome-extensions-samples或直接使用仓库内已就绪的 api-samples/contextMenus/basic 目录以未打包方式加载打开 Chrome 的chrome://extensions开启开发者模式点击加载已解压的扩展程序选择api-samples/contextMenus/basic目录验证效果在任意网页上右键即可看到一组以Test page menu item、Test selection menu item等命名的菜单项、父子菜单结构、radio 与 checkbox 项。点击各菜单项后打开 Service Worker 的控制台chrome://extensions中点击该扩展的Service Worker链接即可看到对应的日志输出。若点击Oops项控制台会打印预期错误信息这正是示例内置的错误处理演示。将控制台日志替换为真实 API 调用即可快速演化出属于自己的右键菜单扩展。小结contextMenus/basic示例用 90 余行代码覆盖了chrome.contextMenusAPI 的全部核心能力上下文类型注册、父子层级、radio / checkbox 状态、统一点击分发与异步错误处理。其onInstalled创建 onClicked分发的结构既是 MV3 的最佳实践也是可复用的通用骨架。结合仓库内global_context_search进阶示例与_archive/mv2历史对照开发者可以快速从演示走向生产级右键菜单功能。【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址: https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考