写html页面没意思,来挑战chrome插件开发

2024-04-21 16:20

本文主要是介绍写html页面没意思,来挑战chrome插件开发,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

谷歌浏览器插件开发是指开发可以在谷歌浏览器中运行的扩展程序,可以为用户提供额外的功能和定制化的体验。谷歌浏览器插件通常由HTML、CSS和JavaScript组成,非常利于前端开发者。
开发者可以利用这些技术在浏览器中添加新的功能、修改现有功能或者与网页进行交互。

要开发谷歌浏览器插件,开发者通常需要创建一个包含*清单文件(manifest.json)、背景脚本(background script)、内容脚本(content script)*等文件的项目结构。清单文件是插件的配置文件,包含插件的名称、版本、描述、权限以及其他相关信息。背景脚本用于处理插件的后台逻辑,而内容脚本则用于在网页中执行JavaScript代码。

谷歌浏览器插件可以实现各种功能,例如添加新的工具栏按钮、修改网页内容、捕获用户输入、与后台服务器进行通信等。开发者可以通过谷歌浏览器插件API来访问浏览器的各种功能和数据,实现各种定制化的需求。
插件开发涉及的要点:

image.png

基础配置

开发谷歌浏览器插件,最重要的文件 manifest.json

{"name": "Getting Started Example",  // 插件名称"description": "Build an Extension!", // 插件描述"version": "1.0", // 版本"manifest_version": 3, // 指定插件版本,这个很重要,指定什么版本就用什么样的api,不能用错了"background": {"service_worker": "background.js" // 指定background脚本的路径},"action": {"default_popup": "popup.html", // 指定popup的路径"default_icon": {  // 指定popup的图标,不同尺寸"16": "/images/icon16.png","32": "/images/icon32.png","48": "/images/icon48.png","128": "/images/icon128.png"}},"icons": { // 指定插件的图标,不同尺寸"16": "/images/icon16.png","32": "/images/icon32.png","48": "/images/icon48.png","128": "/images/icon128.png"},"permissions": [],// 指定应该在脚本中注入那些变量方法,后文再详细说"options_page": "options.html","content_scripts": [ // 指定content脚本配置{"js": [ "content.js"], // content脚本路径"css":[ "content.css" ],// content的css"matches": ["<all_urls>"] // 对匹配到的tab起作用。all_urls就是全部都起作用}]
}
  • name: 插件名称

manifest_version:对应chrome API插件版本,浏览器插件采用的版本,目前共2种版本,是2和最新版3

  • version: 本插件的版本,和发布相关
  • action:点击图标时,设置一些交互
    • default_icon:展示图标
      • 16、32、48、128
    • default_popup:popup.html,一个弹窗页面
    • default_title:显示的标题
  • permissions:拥有的权限
    • tabs:监听浏览器tab切换事件
  • options_ui
  • background:
    • service_worker:设置打开独立页面

官方实例

官方教程

打开pop弹窗页面

设置action的default_popup属性

{"name": "Hello world","description": "show 'hello world'!","version": "1.0","manifest_version": 3,"action": {"default_popup": "popup.html","default_icon": {"16": "/images/icon16.png","32": "/images/icon32.png","48": "/images/icon48.png","128": "/images/icon128.png"}},"permissions":["tabs", "storage", "activeTab", "idle"],"background": {"service_worker": "background.js"},"content_scripts": [{"js": [ "content.js"],"css":[ "content.css" ],"matches": ["<all_urls>"]}]
}

创建popup.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>显示出hello world</title><link rel="stylesheet" type="text/css" href="popup.css"></head><body><h1>显示出hello world</h1><button id="clickBtn">点击按钮</button><script src="popup.js"></script></body>
</html>

文件可以通过链接引入css、js。

body {width: 600px;height: 300px;
}
h1 {background-color: antiquewhite;font-weight: 100;
}
console.log(document.getElementById('clickBtn'));
document.getElementById('clickBtn').addEventListener('click', function () {console.log('clicked');
});

点击插件图标

点击图标可以看到如下的popup的页面。

image.png

调试popup.js的方法

  • 通过弹窗,在弹窗内部点击右键,选择审查内容
    image.png
  • 通过插件图标,进行点击鼠标右键,选择审查弹出内容
    image.png

通过background打开独立页面

基于backgroundservice_workerAPI可以打开一个独立后台运行脚本。此脚本会随着插件安装,初始化执行一次,然后一直在后台运行。可以用来存储浏览器的全局状态数据。
background脚本是长时间运行在后台,随着浏览器打开就运行,直到浏览器关闭而结束运行。通常把需要一直运行的、启动就运行的、全局公用的数据放到background脚本。

chrome.action.onClicked.addListener(function () {chrome.tabs.create({url: chrome.runtime.getURL('newPage.html')});
});

为了打开独立页面,需要修改manifest.json

{"name": "newPage","description": "Demonstrates the chrome.tabs API and the chrome.windows API by providing a user interface to manage tabs and windows.","version": "0.1","permissions": ["tabs"],"background": {"service_worker": "service-worker.js"},"action": {"default_title": "Show tab inspector"},"manifest_version": 3
}

为了实现打开独立页面,在manifest.json中就不能在配置 action:default_popup
newPage.js文件中可以使用*chrome.tabs*和chrome.windowsAPI;
可以使用 chrome.runtime.getUrl 跳转一个页面。

chrome.runtime.onInstalled.addListener(async () => {chrome.tabs.create({url: chrome.runtime.getURL('newPage.html'),});
});

content内容脚本

content-scripts(内容脚本)是在网页上下文中运行的文件。通过使用标准的文档对象模型(DOM),它能够读取浏览器访问的网页的详细信息,可以对打开的页面进行更改,还可以将DOM信息传递给其父级插件。内容脚本相对于background还是有一些访问API上的限制,它可以直接访问以下chrome的API

  • i18n
  • storage
  • runtime:
    • connect
    • getManifest
    • getURL
    • id
    • onConnect
    • onMessage
    • sendMessage

content.js运行于一个独立、隔离的环境,它不会和主页面的脚本或者其他插件的内容脚本发生冲突
有2种方式添加content脚本

在配置中设置

"content_scripts": [{"js": [ "content.js"],"css":[ "content.css" ],"matches": ["<all_urls>"]}
]

content_scripts属性除了配置js,还可以设置css样式,来实现修改页面的样式。
matches表示需要匹配的页面;
除了这3个属性,还有

  • run_at: 脚本运行时刻,有以下3个选项
    • document_idle,默认;浏览器会选择一个合适的时间注入,并是在dom完成加载
    • document_start;css加载完成,dom和脚本加载之前注入。
    • document_end:dom加载完成之后
  • exclude_matches:排除匹配到的url地址。作用和matches相反。

动态配置注入

在特定时刻才进行注入,比如点击了某个按钮,或者指定的时刻
需要在popup.jsbackground.js中执行注入的代码。

chrome.tabs.executeScript(tabs[0].id, {code: 'document.body.style.backgroundColor = "red";',
});

也可以将整个content.js进行注入

chrome.tabs.executeScript(tabs[0].id, {file: "content.js",
});

利用content制作一个弹窗工具

某天不小心让你的女神生气了,为了能够道歉争取到原谅,你是否可以写一个道歉信贴到每一个页面上,当女神打开网站,看到每个页面都会有道歉内容。

image.png

道歉信内容自己写哈,这个具体看你的诚意。
下面设置2个按钮,原谅和不原谅。 点击原谅,就可以关闭弹窗。 点击不原谅,这个弹窗调整css布局位置继续显示。(有点像恶意贴片广告了)

下面设置content.js的内容

let newDiv = document.createElement('div');
newDiv.innerHTML = `<div id="wrapper"><h3>小仙女~消消气</h3><div><button id="cancel">已消气</button><button id="reject">不原谅</button></div>
</div>`;
newDiv.id = 'newDiv';
document.body.appendChild(newDiv);
const cancelBtn = document.querySelector('#cancel');
const rejectBtn = document.querySelector('#reject');
cancelBtn.onclick = function() {document.body.removeChild(newDiv);chrome.storage.sync.set({ state: 'cancel' }, (data) => {});
}
rejectBtn.onclick = function() {newDiv.style.bottom = Math.random() * 200 + 10 + "px";newDiv.style.right = Math.random() * 800 + 10 + "px";
}
// chrome.storage.sync.get({ state: '' }, (data) => {
//   if (data.state === 'cancel') {
//     document.body.removeChild(newDiv);
//   }
// });

content.css布局样式

#newDiv {font-size: 36px;color: burlywood;position: fixed;bottom: 20px;right: 0;width: 300px;height: 200px;background-color: rgb(237, 229, 216);text-align: center;z-index: 9999;
}

打开option页面

options页,就是插件的设置页面,有2个入口

  • 1:点击插件详情,找到扩展程序选项入口

image.png

  • 2插件图标,点击右键,选择 ‘选项’ 菜单

image.png

可以看到设置的option.html页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>插件的option配置</title>
</head>
<body><h3>插件的option配置</h3>
</body>
</html>

此页面也可以进行js、css的引入。

替换浏览器默认页面

override功能,是可以替换掉浏览器默认功能的页面,可以替换newtab、history、bookmark三个功能,将新开页面、历史记录页面、书签页面设置为自定义的内容。
修改manifest.json配置

{"chrome_url_overrides": {"newtab": "newtab.html","history": "history.html","bookmarks": "bookmarks.html"}
}

创建一个newtab的html页面

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><h1>new tab</h1></body>
</html>

插件更新后,点开新的tab,就会出现我们自定义的页面。第一次的情况会让用户进行选择,是进行更换还是保留原来的配置。

image.png
很多插件都是使用newtab进行自定义打开的tab页,比如掘金的浏览器插件,打开新页面就是掘金网站插件。

页面之间进行数据通信

image.png
如需将单条消息发送到扩展程序的其他部分并选择性地接收响应,请调用 runtime.sendMessage() 或 tabs.sendMessage()。通过这些方法,您可以从内容脚本向扩展程序发送一次性 JSON 可序列化消息,或者从扩展程序向内容脚本发送。如需处理响应,请使用返回的 promise。
来源地址:https://developer.chrome.com/docs/extensions/develop/concepts/messaging?hl=zh-cn#simple

content中脚本发送消息

chrome.runtime.sendMessage只能放在content的脚本中。

(async () => {const response = await chrome.runtime.sendMessage({greeting: "hello"});// do something with response here, not outside the functionconsole.log(response);
})();

其他页面发送消息

其他页面需向内容脚本发送请求,请指定请求应用于哪个标签页,如下所示。此示例适用于 Service Worker、弹出式窗口和作为标签页打开的 chrome-extension:// 页面

(async () => {const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true});const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"});// do something with response here, not outside the functionconsole.log(response);
})();

接收消息使用onMessage

在扩展程序和内容脚本中使用相同的代码

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");if (request.greeting === "hello")sendResponse({farewell: "goodbye"});}
);

添加右键菜单

创建菜单

首先在manifest.json的权限中添加配置

{"permissions": ["contextMenus"]
}

background.js中添加创建菜单的代码

let menu1 = chrome.contextMenus.create({type: 'radio', // 可以是 【normal、checkbox、radio】,默认是normaltitle: 'click me',id: "myMenu1Id",contexts:['image'] // 只有是图片时,菜显示
}, function(){})let menu2 = chrome.contextMenus.create({type: 'normal', // 可以是 【normal、checkbox、radio】,默认是normaltitle: 'click me222',id: "myMenu222Id",contexts:['all'] //所有类型都显示
}, function(){})let menu3 = chrome.contextMenus.create({id: 'baidusearch1',title: '使用百度搜索:%s', contexts: ['selection'], //选择页面上的文字
});// 删除一个菜单
chrome.contextMenus.remove('myMenu222Id'); // 被删除菜单的id menuItemId
// 删除所有菜单
chrome.contextMenus.removeAll();// 绑定菜单点击事件
chrome.contextMenus.onClicked.addListener(function(info, tab){if(info.menuItemId == 'myMenu222Id'){console.log('xxx')}
})

以下是其他可以使用的api

// 删除某一个菜单项
chrome.contextMenus.remove(menuItemId)// 删除所有自定义右键菜单
chrome.contextMenus.removeAll();
// 更新某一个菜单项
chrome.contextMenus.update(menuItemId, updateProperties);
// 监听菜单项点击事件, 这里使用的是 onClicked
chrome.contextMenus.onClicked.addListener(function(info, tab)) {//...
});

绑定点击事件,发送接口请求

首先需要在manifest.jsonhosts_permissions中添加配置

{"host_permissions": ["http://*/*", "https://*/*"]
}

创建node服务器,返回json数据

// server.mjs
const { createServer } = require('node:http');
const url = require('url');const server = createServer((req, res) => {var pathname = url.parse(req.url).pathname;if (pathname.includes('api')) {res.writeHead(200, { 'Content-Type': 'application/json' });res.write(JSON.stringify({name: 'John Doe',age: 30,}));res.end();} else {res.writeHead(200, { 'Content-Type': 'text/plain' });res.end('Hello World!\n' + pathname);}
});server.listen(8080, '127.0.0.1', () => {console.log('Listening on 127.0.0.1:8080');
});

编辑background.js文件

// 插件右键快捷键
// 点击右键进行选择
chrome.contextMenus.onClicked.addListener(function (info, tab) {if (info.menuItemId === 'group1') {console.log('分组文字1', info);}if (info.menuItemId === 'group2') {console.log('分组文字2');}// 点击获取到数据if (info.menuItemId === 'fetch') {console.log('fetch 获取数据');const res = fetch('http://localhost:8080/api', {method: 'GET',headers: {'Content-Type': 'application/json',},}).then((res) => {console.log(res, '获取到http://localhost:8080/api接口数据');chrome.storage.sync.set({ color: 'red' }, function (err, data) {console.log('store success!');});});}// 创建百度搜索,并跳转到搜索结果页if (info.menuItemId === 'baidusearch1') {// console.log(info, tab, "baidusearch1")// 创建一个新的tab页面chrome.tabs.create({url:'https://www.baidu.com/s?ie=utf-8&wd=' + encodeURI(info.selectionText),});}
});// 创建右键快捷键
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,//   });// }// Create a parent item and two children.let parent = chrome.contextMenus.create({title: '操作数据分组',id: 'parent',});chrome.contextMenus.create({title: '分组1',parentId: parent,id: 'group1',});chrome.contextMenus.create({title: '分组2',parentId: parent,id: 'group2',});chrome.contextMenus.create({title: '获取远程数据',parentId: parent,id: 'fetch',});// Create a radio item.chrome.contextMenus.create({title: '创建单选按钮1',type: 'radio',id: 'radio1',});chrome.contextMenus.create({title: '创建单选按钮2',type: 'radio',id: 'radio2',});// Create a checkbox item.chrome.contextMenus.create({title: '可以多选的复选框1',type: 'checkbox',id: 'checkbox',});chrome.contextMenus.create({title: '可以多选的复选框2',type: 'checkbox',id: 'checkbox2',});// 在title属性中有一个%s的标识符,当contexts为selection,使用%s来表示选中的文字chrome.contextMenus.create({id: 'baidusearch1',title: '使用百度搜索:%s',contexts: ['selection'],});// 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);}});
});

点击鼠标右键,效果如下

image.png

image.png

如果在页面选择几个文字,那么就显示出百度搜索快捷键,

image.png

缓存,数据存储

首先在manifest.json的权限中添加storage配置

{"permissions": ["storage"]
}
chrome.storage.sync.set({color: 'red'}, function(){console.log('background js storage set data ok!')
})

然后就可以在content.js或popup.js中获取到数据

// 这里的参数是,获取不到数据时的默认参数
chrome.storage.sync.get({color: 'yellow'}, function(){console.log('background js storage set data ok!')
})

tabs创建页签

首先在manifest.json的权限中添加tabs配置

{"permissions": ["tabs"]
}

添加tabs的相关操作

chrome.tabs.query({}, function(tabs){console.log(tabs)
})
function getCurrentTab(){let [tab] = chrome.tabs.query({active: true, lastFocusedWindow: true});return tab;
}

notifications消息通知

Chrome提供chrome.notifications的API来推送桌面通知;首先在manifest.json中配置权限

{"permissions": ["notifications"],
}

然后在background.js脚本中进行创建

// background.js
chrome.notifications.create(null, {type: "basic",iconUrl: "drink.png",title: "喝水小助手",message: "看到此消息的人可以和我一起来喝一杯水",
});

devtools开发扩展工具

在manifest中配置一个devtools.html

{"devtools_page": "devtools.html",
}

devtools.html中只引用了devtools.js,如果写了其他内容也不会展示

<!DOCTYPE html>
<html lang="en"><head> </head><body><script type="text/javascript" src="./devtools.js"></script></body>
</html>

创建devtools.js文件

// devtools.js
// 创建扩展面板
chrome.devtools.panels.create(// 扩展面板显示名称"DevPanel",// 扩展面板icon,并不展示"panel.png",// 扩展面板页面"Panel.html",function (panel) {console.log("自定义面板创建成功!");}
);// 创建自定义侧边栏
chrome.devtools.panels.elements.createSidebarPane("Sidebar",function (sidebar) {sidebar.setPage("sidebar.html");}
);

然后在创建自定的Panel.html和sidebar.html页面。

相关代码下载

这篇关于写html页面没意思,来挑战chrome插件开发的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/923519

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

跨国公司撤出在华研发中心的启示:中国IT产业的挑战与机遇

近日,IBM中国宣布撤出在华的两大研发中心,这一决定在IT行业引发了广泛的讨论和关注。跨国公司在华研发中心的撤出,不仅对众多IT从业者的职业发展带来了直接的冲击,也引发了人们对全球化背景下中国IT产业竞争力和未来发展方向的深思。面对这一突如其来的变化,我们应如何看待跨国公司的决策?中国IT人才又该如何应对?中国IT产业将何去何从?本文将围绕这些问题展开探讨。 跨国公司撤出的背景与

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来