chrome V3 插件开发 基础

目录

小白学习chrome 插件开发,如果有什么不对的,请指教
注意: 用的是 chrome V3

准备

  1. 创建文件夹 myPlugin
  2. myPlugin 文件中创建 manifest.json 文件
  3. myPlugin 文件中创建 icons 文件文件夹,并且在icons 文件中准备一个图片
  4. 配置 manifest.json
    更多参数配置可以查看官网:Manifest file format
json 复制代码
{
  "name": "插件",
  "version": "1.0",
  "manifest_version": 3,
  "description": "学习chrome插件开发",
  "author": "chenss",
  "icons": {
      "16": "icons/logo.png",
      "48": "icons/logo.png", 
      "128": "icons/logo.png"
  }
}
  1. 打开 管理扩展插件,把myPlugin 添加进来就能看到了,如果图标不正确可以点击刷新,如果还不行请检查配置路径

准备工作就到这里了,如果你一切顺利,我们继续吧~

popup

创建 popup.htmlpopup.js

popup.html

html 复制代码
<!DOCTYPE html>
<head>
  <meta charset="utf-8" />
  <body>
    <div>chenss</div>
  </body>
</head>

配置 manifest.json

javascript 复制代码
...
"action": {
   "default_popup": "popup.html"
}

点击插件,就能弹出一个弹框啦~~~

通信

简单通信使用 runtime.sendMessage() tabs.sendMessage()发消息,在接收端使用 runtime.onMessage 来接收消息。

在根目录新建content-script.js,配置 manifest.json

json 复制代码
...
"action": {
  "default_popup": "popup.html"
},
"content_scripts": [
  {
      "matches": ["*://*/*","<all_urls>"],
      "js": ["content-script.js"]
  }
],
"permissions": ["tabs"]

popup.html 添加按钮

javascript 复制代码
<div>
  <div class="box">
    <button id="backgroud">给bg发消息</button>
  </div>
  <script src="popup.js"></script>
</div>

popupbackground 分别添加如下代码

javascript 复制代码
// 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);
}
javascript 复制代码
// background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  console.log('这是background脚本onMessage', message);
  sendResponse("收到消息");
});

接下来我们看看效果:

点开这个地方

当然 你也可以使用 chrome.runtime.sendMessage 发消息

javascript 复制代码
// popup.js
let sendBg = document.getElementById("backgroud");
sendBg.onclick = async function () {
  chrome.runtime.sendMessage({greeting:"hello"}, function(response) {
  console.log(response);
}
  1. 同样在 popup.html 添加按钮
  2. popupbackground 分别添加如下代码
javascript 复制代码
// 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);
}
javascript 复制代码
// 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.connecttabs.connect

建立连接时,两端都将获得一个 runtime.Port 对象,用来通过建立的连接发送和接收消息。

更多详细内容可以看文档,本次只用runtime.connect举列子。

  1. 同样在 popup.html 添加按钮
  2. popupbackground 分别添加如下代码
javascript 复制代码
// 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" });
  });
};
javascript 复制代码
// 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 workercontent scripts 发送建立连接请求时,若目标 tab 中存在多个 iframe ,且 content scripts 注入到了每个 iframe 中,则每个 iframe 中的 runtime.onConnect 事件都会被触发。同样的,也可能会出现多个 iframe 中的runtime.connect() 一起调用的情况。

如何页面上添加一个按钮?

tabs.onUpdated

使用 tabs.onUpdated , 再次强调一下需要配置permissions: ['tabs'],并且需要重新加载插件,如重新加载还是无法生效,请移除插件重新导入

background.js 代码如下:

javascript 复制代码
//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

javascript 复制代码
// 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 中配置

javascript 复制代码
"web_accessible_resources": [ {
     "resources": ["inject.js"],
     "matches": [ "*://*/*" ]
 }],

"matches" :字符串数组,每个字符串都包含一个匹配模式,指定哪些站点可以访问这组资源。仅使用来源来匹配 URL。例如"matches": [ "http://*/*" ] 这样配置的话,https开头网址的页面上看不到按钮。当然可以利用正则匹配网页地址。

javascript 复制代码
//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 文档地址

在项目的manifest.json文件的permissions中加上contextMenus

javascript 复制代码
"permissions": [
   "contextMenus"
]

方法

创建菜单方法如下,属性具体请看文档,下面只是列举了几个常用的属性:

javascript 复制代码
chrome.contextMenus.create({
    type: 'normal',
    title: 'Menu Demo',
    id: 'menuDemo',//要分配给此项的唯一 ID。活动页面的强制性。不能与此扩展的另一个 ID 相同。
    contexts: ['all'],
    enabled:true,//是否启用或禁用此上下文菜单项。默认值为true
    parentId:""//父菜单项的 ID; 这使该项成为以前添加的项的子项。
    onclick: genericOnClick //点击事件,跟的就是处理的方法名,如genericOnClick,就是对应的一个function
}, function () {
    console.log('contextMenus are create.');
});

其它方法包括 removeremoveAllupdate。在此不赘述,可以看文档,下面的列子中也有使用。

事件

单击上下文菜单项时触发使用chrome.contextMenus.onClicked

javascript 复制代码
chrome.contextMenus.onClicked.addListener(
  callback: function,
)

举个例子添加

background.js 里面添加如下代码

javascript 复制代码
//background.js
chrome.runtime.onInstalled.addListener(() => {
  createMenus()
});
// 自定义右键菜单
function createMenus() {
  chrome.contextMenus.create({
    title: "菜单操作-events", //菜单的名称
    id: "01", //一级菜单的id
    contexts: ["page"], // page表示页面右键就会有这个菜单,如果想要当选中文字时才会出现此右键菜单,用:selection
  });

  chrome.contextMenus.create({
    title: "removeAll",
    id: "02",
    contexts: ["page"],
  });

  chrome.contextMenus.create({
    title: "更新菜单",
    id: "03",
    contexts: ["page"],
  });

  chrome.contextMenus.create({
    title: "删除菜单",
    id: "04",
    contexts: ["page"],
  });
  
  chrome.contextMenus.onClicked.addListener((info, tab) => {
    if (info.menuItemId == "01") {
      //跳转页面
      chrome.tabs.create({
        url:"https://www.baidu.com/" 
      });
    } else if (info.menuItemId == "02") {
      //移除此扩展插件添加的所有上下文菜单项。
      chrome.contextMenus.removeAll();
    } else if (info.menuItemId == "03") {
      //更新菜单
      chrome.contextMenus.update("03",{
          type: 'checkbox',
          title: "更新之后菜单", //菜单的名称
          checked: false,
      });
    }else if (info.menuItemId == "04") {
      //删除指定菜单
      chrome.contextMenus.remove("04",()=>{});
    }
  });
}

这样就添加成功了

关于报错(cannot create item with duplicate id XXX)]

例如:一开始的时候在onUpdated 周期添加菜单

javascript 复制代码
chrome.tabs.onUpdated.addListener(async function(tabId,changeInfo,tab){
    chrome.contextMenus.create({
    ...
    })
});

每次刷新页面的时候就会出现这个重复添加的错误:

是因为 onUpdated 状态是loading 和 complate 的时候重复添加了,当然可以判断一下加载状态,再去创建。

如果你通过通信方式添加菜单也需要注意,也会存在这个问题。

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

未完待续👻👻👻👻👻👻👻👻

相关推荐
m0_748256147 分钟前
前端 MYTED单篇TED词汇学习功能优化
前端·学习
小白学前端6661 小时前
React Router 深入指南:从入门到进阶
前端·react.js·react
web130933203982 小时前
前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案
前端
outstanding木槿2 小时前
react+antd的Table组件编辑单元格
前端·javascript·react.js·前端框架
好名字08212 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
隐形喷火龙3 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
m0_748241123 小时前
Selenium之Web元素定位
前端·selenium·测试工具
风无雨3 小时前
react杂乱笔记(一)
前端·笔记·react.js
前端小魔女3 小时前
2024-我赚到自媒体第一桶金
前端·rust
鑫~阳3 小时前
快速建站(网站如何在自己的电脑里跑起来) 详细步骤 一
前端·内容管理系统cms