【教程向】从零开始创建浏览器插件(六)实战篇
【教程向】从零开始创建浏览器插件(六)实战篇
在这篇文章中,我们将详细介绍一个名为“摸鱼King”的Chrome扩展程序的开发思路。这个扩展程序的主要功能是在用户浏览网页时提供便捷的方式来摸鱼看小说。
完整的工程我放在了完整工程,可以下载下来自己试一试。
1. 主要功能和组件
我们以一个摸鱼看小说的插件为例,需要实现导入(存储)小说、选择(读取)小说、设置分页参数、渲染小说文字展示、快捷键等功能。
-
名称和版本:
- 名称:摸鱼King
- 版本:1.0
- 描述:摸鱼看小说
-
权限需求:
- [activeTab]允许扩展访问当前活动标签页的信息。
- [storage]允许扩展存储和检索数据。
- [scripting]允许扩展运行脚本。
-
背景脚本:
- 使用[background.js]作为服务工作线程,这是manifest v3中推荐的方式,可以有效管理和维护扩展的后台逻辑。
-
弹出页面:
- 默认弹出页面设置为[popup/popup.html],用户可以通过点击扩展图标来触发这个页面,进行更多交互操作。
-
内容脚本:
- [content/content.js]在所有网页上运行(由
<all_urls>匹配),并在文档加载结束时执行。这允许扩展在网页内容完全加载后修改或访问网页内容。
- [content/content.js]在所有网页上运行(由
-
图标:
- 使用[icon128.png]作为扩展的默认图标,显示在浏览器的扩展栏中。
2. 开发思路
开发这个扩展程序的主要思路是提供一个简单而直接的方式来增强用户的浏览体验,通过在浏览器中直接提供摸鱼看小说的功能。通过内容脚本,扩展可以在用户浏览网页时插入小说内容或相关功能,而不干扰网页的主要功能。
- 背景脚本处理扩展的核心逻辑,如数据存储和跨标签页的操作。
- 弹出页面提供用户界面,使用户可以进行简单的交互,如选择小说或调整设置。
- 内容脚本直接与网页交互,插入或修改网页内容,提供摸鱼功能。
3.项目初始化
由上面的思路我们可以整理出一个项目结构目录以及一个manifest配置文件。
目录结构:
moyuKing/
│
├── manifest.json
│
├── background.js # 背景脚本
│
├── popup/ # 弹出页面目录
│ └── popup.html # 弹出页面HTML
│ └── popup.js # 弹出页面JS
│ └──popup.css # 弹出页面CSS
│
├── content/ # 内容脚本目录
│ └── content.js # 内容脚本
│
└── icon128.png # 扩展图标
manifest.json
{"manifest_version": 3,"name": "摸鱼king","version": "1.0","description": "摸鱼看小说","permissions": ["activeTab","storage","scripting"],"background": {"service_worker": "background.js"},"action": {"default_popup": "popup/popup.html","default_icon": {"128": "icon128.png"}},"content_scripts": [{"matches": ["<all_urls>"],"js": ["content/content.js"],"run_at": "document_end"}],"icons": {"128": "icon128.png"}
}
4.background.js
背景脚本主要实现数据存储和另外两个脚本之间的数据通信。
IndexedDB 是一种运行在浏览器中的非关系型数据库,适合于存储大量结构化数据,我们选用它来实现数据存储,以下代码打开数据库、创建对象存储、读写数据以及更新数据等操作。
初始化数据库
IndexedDB的操作首先是创建或打开一个数据库。我们定义了一个IDBUtil对象,封装了与数据库操作相关的方法。
const IDBUtil = {dbName: "myDatabase",storeName: "idStore",version: 1,async openDB() {return new Promise((resolve, reject) => {const request = indexedDB.open(this.dbName, this.version);request.onerror = (event) => reject(event.target.errorCode);request.onupgradeneeded = (event) => {const db = event.target.result;if (!db.objectStoreNames.contains(this.storeName)) {db.createObjectStore(this.storeName, { keyPath: "id" });}};request.onsuccess = (event) => resolve(event.target.result);});},// 其他方法...
};
在openDB方法中,我们检查数据库是否存在指定的对象存储,如果不存在,则创建一个新的对象存储。keyPath为对象存储的主键。
数据读写
在IndexedDB中,数据的读写需要通过事务来完成。以下是如何插入和检索数据的示例:
async setId(id) {const db = await this.openDB();const transaction = db.transaction(this.storeName, "readwrite");const store = transaction.objectStore(this.storeName);const request = store.put({ id: "unique", value: id });return new Promise((resolve, reject) => {request.onsuccess = () => resolve();request.onerror = (event) => reject(event.target.errorCode);});
},async getId() {const db = await this.openDB();const transaction = db.transaction(this.storeName, "readonly");const store = transaction.objectStore(this.storeName);const request = store.get("unique");return new Promise((resolve, reject) => {request.onsuccess = (event) => resolve(request.result ? request.result.value : null);request.onerror = (event) => reject(event.target.errorCode);});
},
在这里,setId方法通过事务在对象存储中存储了一个ID值,而getId方法则用来检索这个值。
更新数据
数据的更新可以复用之前的插入逻辑,因为IndexedDB的put方法会替换已有的数据记录:
async updateId(newId) {return this.setId(newId);
},
扩展功能
除了基础的数据库操作,我们还展示了如何在浏览器扩展的background脚本中实现更复杂的逻辑,例如更新页面信息、保存文件内容等。这些操作同样基于IndexedDB事务来实现数据的一致性。
const updatePageInfo = async (id, pageNum, pageSize) => {const db = await openDB();const transaction = db.transaction(["files"], "readwrite");const store = transaction.objectStore("files");const request = store.get(id);request.onsuccess = () => {const data = request.result;data.pageNum = pageNum;data.pageSize = pageSize;store.put(data);};
};
在updatePageInfo方法中,我们首先通过ID获取文件记录,然后更新其页码和页面大小信息。
完整代码
除此之外,我们还需要提供几个事件的监听来实现数据通信,完整代码如下:
const IDBUtil = {dbName: "myDatabase",storeName: "idStore",version: 1, // 可以根据需要更新数据库结构时增加版本号// 打开(或初始化)数据库async openDB() {return new Promise((resolve, reject) => {const request = indexedDB.open(this.dbName, this.version);request.onerror = (event) => {console.error("Database error:", event.target.errorCode);reject(event.target.errorCode);};// 第一次创建数据库或版本更新时触发request.onupgradeneeded = (event) => {const db = event.target.result;// 创建一个新的存储对象if (!db.objectStoreNames.contains(this.storeName)) {db.createObjectStore(this.storeName, {keyPath: "id",autoIncrement: false,});}};request.onsuccess = (event) => {console.log("Database opened successfully");resolve(event.target.result);};});},// 设置ID值async setId(id) {const db = await this.openDB();const transaction = db.transaction(this.storeName相关文章:
【教程向】从零开始创建浏览器插件(六)实战篇
【教程向】从零开始创建浏览器插件(六)实战篇 在这篇文章中,我们将详细介绍一个名为“摸鱼King”的Chrome扩展程序的开发思路。这个扩展程序的主要功能是在用户浏览网页时提供便捷的方式来摸鱼看小说。 完整的工程我放在了完整工程,可以下载下来自己试一试。 1. 主要功能…...
如何用 OceanBase做业务开发——【DBA从入门到实践】第六期
当应用一款新的数据库时,除了基础的安装部署步骤,掌握其应用开发方法才是实现数据库价值的关键。为此,我们特别安排了5月15日(周三)的《DBA 从入门到实践》第六期课程——本次课程将带大家了解OceanBase数据库的开发流…...
Element-UI快速入门
作者介绍:✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目:CSDN主页YAML墨韵 学如逆水行舟,…...
【JavaWeb】网上蛋糕商城后台-商品管理
概念 本文讲解和实现网上蛋糕商城的后台管理系统中的商品管理功能。 商品列表 点击后台管理系统的head.jsp头部的“商品管理”功能选项,向服务器发送请求/admin/goods_list 因此需要在servlet包中创建AdminGoodsListServlet类,用于获取商品信息列表 …...
Django Admin后台管理:高效开发与实践
title: Django Admin后台管理:高效开发与实践 date: 2024/5/8 14:24:15 updated: 2024/5/8 14:24:15 categories: 后端开发 tags: DjangoAdmin模型管理用户认证数据优化自定义扩展实战案例性能安全 第1章:Django Admin基础 1.1 Django Admin简介 Dj…...
Centos7网卡启动失败(Failed to start LSB: Bring up/down)
好雨知时节 当春乃发生 随风潜入夜 润物细无声 报错内容 启动虚拟机时,Ceotos的虚拟网卡没有一起启动,导致服务无法正常使用 查询网络启动状态 systemctl status network.service报Failed to start LSB: Bring up/down 查看网络启动日志 journalctl…...
【NOIP2008普及组复赛】 题4:立体图
题4:立体图 【题目描述】 小渊是个聪明的孩子,他经常会给周围的小朋友讲些自己认为有趣的内容。最近,他准备给小朋友讲解立体图,请你帮他画出立体图。 小渊有一块面积为mn的矩形区域,上面有mn个边长为1的格子&#…...
【Leetcode每日一题】 动态规划 - 简单多状态 dp 问题 - 删除并获得点数(难度⭐⭐)(76)
1. 题目解析 题目链接:LCR 091. 粉刷房子 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 1. 状态定义 在解决这类问题时,我们首先需要根据题目的具体要求来定义状态。针对房屋粉刷问题&#…...
Windows---CMD常用指令大全
CMD是什么? Windows操作系统中的命令行界面程序,全称为命令提示符 CMD可以干什么? 允许用户在文本界面下输入命令来执行各种操作,如文件管理、系统设置、软件安装等 帮助用户更好地控制和管理Windows系统 windows系统CMD指…...
消息中间件是什么?有什么用?常见的消息中间件有哪些?
1.什么是消息中间件? 消息中间件基于队列模型在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。 2.现实中的痛点: 1.Http请求基于请求与响应的模型,在高并发的情况下,客户端发送大量的请求达到服务器端…...
富锂锰基材料极具发展潜力 我国产业化进程加速
富锂锰基材料极具发展潜力 我国产业化进程加速 富锂锰基材料以锰元素为主,我国锰资源较丰富,相比于铁锂材料、高镍三元材料,富锂锰基材料具有一定的降本潜力。此外富锂锰基材料在能量密度、充放电倍率等方面也具有明显优势。富锂锰基材料是富…...
聚水潭和金蝶云星空单据接口对接
聚水潭和金蝶云星空单据接口对接 对接系统:金蝶云星空 金蝶K/3Cloud(金蝶云星空)是移动互联网时代的新型ERP,是基于WEB2.0与云技术的新时代企业管理服务平台。金蝶K/3Cloud围绕着“生态、人人、体验”,旨在帮助企业打造…...
OpenAI深夜震撼发布最新模型GPT-4o,送上最快速便捷教程
北京时间5月14日凌晨,有人说OpenAI一夜改变了历史。 在我们的深夜、太平洋时间的上午 10 点,OpenAI 召开春季发布会,公布了最新的GPT-4o模型,o代表Omnimodel(全能模型)。20多分钟的演示直播,展…...
没有申请域名的情况下,用navicat远程连接我们的服务器的Mysql数据库
我们可以根据公网ip用shell来远程连接 首先我们打开自己买的服务器 例如你看这个,就是我们的公网IP 如果服务器里面没有安装mysql数据库的话,那么我们可以用一个轻量级的docker来安装数据库代替一下 我们用docker弄个轻量级的mysql5.7.36,…...
Hive中小文件过多的几种处理方式
1、使用concatenate(只支持RCFile和ORC格式) 2、减少map数量,调整参数:输入合并文件相关的参数 3、减少reduce的数量(例如直接设置reduce为xx个、或者设置reduce的大小,系统自动根据大小确定reduce的个数…...
用户登录认证和权限授权(SpringSecurity、JWT、session)
文章目录 前言一、登录认证1. 问题引入2. Session2.1 实现原理2.2 过滤器Filter2.3 上下文对象 3. JWT3.2 实现步骤3.3 拦截器 HandlerInterceptorAdapter3.4 上下文对象 4. Session VS JWT 二、权限授权1. 权限类型1.1 页面权限(菜单项权限)1.2 ACL模型…...
第十二届蓝桥杯省赛真题 Java A 组【原卷】
文章目录 发现宝藏【考生须知】试题 A: 相乘试题 B: 直线试题 C : \mathrm{C}: C: 货物摆放试题 D: 路径试题 E: 回路计数试题 F : \mathrm{F}: F: 最少砝码试题 G: 左孩子右兄弟试题 H : \mathrm{H}: H: 异或数列试题 I \mathbf{I} I 双向排序试题 J : \mathrm{J}: J: 分…...
工作随机:linux 挂载LVM管理模式的磁盘
文章目录 前言一、创建一个分区二、创建PV三、创建VG四、创建LV五、格式化并挂载目录 前言 在数据库管理中,常有比较头疼的问题,就是一段时间发展后我的磁盘空间不够了,想要扩容原有的目录很是头疼,那么LVM管理的优势就体现出来了…...
打印kafka最近的消息
使用 kafka-run-class 指令,获取topic的最小offset和最大offset #查看各个分区的最小offset(这个意思就是,这个offset之前的消息已经被清除了,现在consumer是从这个offset之后开始消费): ./kafka-run-class.sh kafka.tools.GetOffsetShell …...
e行64位V11.17.4 安卓全局虚拟定位APP
e行最新版11.17.4 支持全局虚拟位置 小米手机 百度地图 高德地图 实测成功 其他app自测 不一定支持所有app 下载:https://www.123pan.com/s/HAf9-tsyCh.html...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
