Chrome插件开发-右键菜单开启页面编辑

本文介绍了如何开发一个Chrome插件,通过manifest.json配置content_scripts和background.js来执行JS脚本改变页面DOM。插件利用contextMenusAPI添加右键菜单,实现页面编辑功能的开启和关闭。内容脚本与背景脚本之间通过ChromeAPI进行通信,背景脚本处理右键菜单的点击事件并发送消息给content_script执行相应操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开发一个执行js脚本改变页面DOM的Chrome插件,manifest_version版本为3。

Chrome插件基本知识

Chrome插件通常由以下几部分组成:
  • manifest.json

该文件为必须项,其它文件都是可选的。该文件相当于插件的meta信息,包含manifest版本、插件名称、插件版本、插件描述、popup、background、content等配置。


  • content script

通过manifest.json的content_scripts配置,可用正则匹配决定该脚本需要在哪些网站的页面执行。该脚本直接作用于具体的页面,是插件注入到页面的脚本,但是不会体现在页面DOM结构里,相当于我们F12后在控制台执行脚本。content_scripts可以操作DOM,但是它和页面其他的脚本是隔离的,访问不到其他脚本定义的变量、函数等,相当于运行在单独的沙盒里。content script可以调用有限的Chrome插件API,网络请求受到同源策略限制。


  • popup

通过manifest.json的action下的default_popup配置,点击插件栏的插件图标后的弹出页面。


  • background.js

通过manifest.json的background下的service_worker配置,可以调用全部的Chrome插件API,实现跨域请求、网页截屏、弹出Chrome通知消息等功能。该页面的输出信息可以在【扩展程序】找到对应插件,点开【查看视图】后面的【Service Worker】,在弹出窗口中查看。

content、popup、background之间的通信

每个页面都会有一个content和popup,所有页面共用一个background。它们之间的通信需要使用Chrome API,具体用法可以参考官方文档。本文代码仅展示background和content的通信。

代码实现

把以下文件放在同一个文件夹中,打开Chrome的插件界面,打开开发者模式,直接把文件夹拖进Chrome的插件界面即可。


manifest.json

{
    "manifest_version": 3,
    "name": "开启/关闭页面编辑",
    "version": "0.0.1",
    "description": "鼠标右键菜单开启/关闭页面编辑功能",
    "action": {
        "default_icon": "./icon.png",
        "default_popup": "./popup.html"
    },
    "icons": {
        "16": "./icon_16.png"
    },
    "permissions": [
        "contextMenus",
        "tabs",
        "notifications"
    ],
    "background": {
        "service_worker": "./background.js"
    },
    "content_scripts": [
        {
            "matches": [
                "http://*/*",
                "https://*/*"
            ],
            "run_at": "document_idle",
            "js": [
                "./content-script.js"
            ]
        }
    ]
}

content-script.js

chrome.runtime.onMessage.addListener((data, pluginInfo) => {
    console.log("data:", JSON.stringify(data));
    console.log("pluginInfo:", JSON.stringify(pluginInfo));
    if (data.menuInfo.parentMenuItemId != "editHtml") {
        console.log("不是页面编辑开启/关闭按钮");
        return;
    }
    document.body.contentEditable = data.menuInfo.menuItemId == "editHtmlOn";
});

background.js

// 右键一级菜单
chrome.contextMenus.create({
    title: '开启/关闭页面编辑',
    id: 'editHtml',
    contexts: ['all'],
    type: "normal" // "normal", "checkbox", "radio", "separator"
}, () => {
    console.log('contextMenus are created.');
});

// 右键二级菜单-关闭
chrome.contextMenus.create({
    title: '关闭',
    id: 'editHtmlOff',
    parentId: "editHtml",
    contexts: ['all'],
    type: "radio", // "normal", "checkbox", "radio", "separator"
    checked: true
}, () => {
    console.log('OFF contextMenus are created.');
});

// 右键二级菜单-开启
chrome.contextMenus.create({
    title: '开启',
    id: 'editHtmlOn',
    parentId: "editHtml",
    contexts: ['all'],
    type: "radio", // "normal", "checkbox", "radio", "separator"
    checked: false
}, () => {
    console.log('ON contextMenus are created.');
});

// 监听右键菜单被点击事件
chrome.contextMenus.onClicked.addListener((menuInfo, tabInfo) => {
    // 菜单信息,具体内容请自行查看调试窗口的调试日志
    console.log("menuInfo:", JSON.stringify(menuInfo))
    // 页面信息,具体内容请自行查看调试窗口的调试日志
    console.log("tabInfo:", JSON.stringify(tabInfo))

    chrome.tabs.query({
        active: true, currentWindow: true
    }, (tabs) => {
        // 页签信息,具体内容请自行查看调试窗口的调试日志
        console.log("tabs:", JSON.stringify(tabs))
        // 向当前页签(即tabs[0])发送消息
        chrome.tabs.sendMessage(tabs[0].id,
            {
                menuInfo: menuInfo,
                tabInfo: tabInfo,
                msg: "msg from background"
            },
            (res) => {
                console.info(JSON.stringify("res:", res));
                if (res) {
                    // 发送系统通知
                    chrome.notifications.create("reminder", {
                        type: "basic",
                        iconUrl: "notifications.png",
                        title: "出错!!!",
                        message: "开启页面编辑出错!!!" + JSON.stringify(res)
                    })
                    return;
                }
                // 发送系统通知
                chrome.notifications.create("reminder", {
                    type: "basic",
                    iconUrl: "./notifications.png", // 通知使用的图标
                    title: (menuInfo.menuItemId == "editHtmlOn" ? "已开启" : "已关闭") + "编辑功能", // 通知标题,一定要有内容,哪怕是空字符串,否则不会发送通知
                    message: "当前页面已" + (menuInfo.menuItemId == "editHtmlOn" ? "开启" : "关闭") + "编辑功能" // 通知内容,一定要有内容,哪怕是空字符串,否则不会发送通知
                })
            })
    })
});

popup.html

<!DOCTYPE html>
<html>

<head>
    <meta charset='utf-8'>
</head>

<body>
    <h1 id="title" style="color:blueviolet;background-color: orange;">这是一个示例popup</h1>
</body>

</html>

icon.png & icon_16.png & notifications.png

随便找些图片就行

参考

chrome 插件开发指南

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值