Chrome插件开发入门
最近学习了Chrome插件的开发,总体来说上手还是很容易的,因为浏览器插件本质上依旧是网页,写几个demo基本就了解了他的开发过程。
什么是Chrome插件
正如开头所说的,Chrome插件实际上就是一个网页,由HTML、CSS、JS、图片等资源组成,与网页不同的是,Chrome插件是用来增强浏览器功能的,同时它还有一套属于自己的开发规则和API。
每个插件都由不同的组件构成,这些组件大都包括background scripts,content scripts,options page,UI以及各种逻辑文件,当然,这些文件是否需要是根据插件的功能所决定的。
接下来我将通过开发一个获取页面图片并保存的插件来介绍如何开发一个Chrome插件。
获取页面上的图片
首先,我们需要一个目录来存放这个插件的各个文件。
创建manifest
manifest.json是一个Chrome插件必不可少的文件,它包含了你插件的所有信息。
{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3
}
只要在目录中包含manifest.json,这个目录就可以被作为一个Chrome插件添加到Chrome当中。
- 在浏览器地址栏中输入
chrome://extensions,回车以打开浏览器的扩展程序界面 - 打开开发人员模式
- 点击
加载已解压的扩展程序,选择manifest文件所在的目录
这样我们就成功安装了一个扩展,接下来我们要在此基础上完善它。
用户界面
一个插件可以有多种形式的用户界面,这里我们选择弹出层作为用户界面,在插件根目录下创建一个popup.html,这个页面需要包含两个按钮分别用来触发获取图片和保存图片的事件,以及一个用来展示图片的盒子。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
body,
img {
width: 400px;
}
</style>
</head>
<body>
<button id="get">获取</button>
<button id="save">保存</button>
<div id="app"></div>
</body>
</html>
注意,如果在popup.html中有中文出现,一定要在head标签中添加<meta charset="UTF-8" />,以防止出现乱码。
创建完成后,我们需要在manifest.json中声明该页面,以保证浏览器能够正确的读取到它。添加一个action对象,同时将popup.html设置为该对象的default_popup。
{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
},
}
为了让我们的插件像个正经的插件,给他添加上图标。我们需要准备16x16、32x32、48x48以及128x128四种大小的图标图片,将它们放到目录中,之后将它们的路径写入manifest.json中。
{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
}
为了让图标能够在扩展程序管理页面显示,我们还需要添加一个icons对象。
{
"name": "获取图片",
"description": "获取页面上的所有图片",
"version": "1.0",
"manifest_version": 3,
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
"icons": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
}
点击扩展程序管理页面中的更新按钮,即可看到添加完用户界面的插件信息了。
功能逻辑
之后我们要为插件添加它应有的功能——获取页面图片。
首先我们先简单梳理一下需求:
- 点击popup.html中的获取按钮,拿到当前页面的图片
- 点击popup.html中的保存按钮,将拿到的图片保存下来
实际上我们的插件与当前正在活动的页面并不是同一个页面,因此我们需要通过某种方式来将获取图片的js代码发送到当前活动页上,并且还需要这段js代码能够在获取到图片之后将图片发送到popup.html中。
这里我们就需要用到一开始提到的content scripts组件以及content script与popup之间通信的API。content scripts简单来说就是插入页面的脚本,虽说是插入页面的脚本,实际上它与页面原本的js是分割开的,双方不能获取到对方的变量、函数等内容。不过content scripts还是可以获取到dom的。
获取图片
首先添加一个content-script.js,这个脚本主要有两个功能,一是获取图片,二是监听popup传来的消息,然后将获取到的图片作为回信传回去。
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// message的数据格式取决于发送时的数据
const { start } = message;
if (start) {
const images = document.getElementsByTagName('img');
const imgSrcList = Array.from(images).map((img) => img.src);
sendResponse(imgSrcList);
}
});
之后我们要在manifest.json中声明配置它
{
...
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"js/content-script.js"
]
}
]
}
matches声明了content scripts要注入的页面,<all_urls>表示所有页面,js属性声明了要注入的js脚本,除此之外还有css属性声明要注入的css代码、run_at属性声明注入时机等都可以在官方文档中找到。
之后添加一个popup.js为界面上的按钮注册点击事件,并在popup.html中引入它
let srcList;
const getImageBtn = document.getElementById('get');
getImageBtn.addEventListener('click', async () => {
// 获取当前活动页
chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
let message = { start: true };
// 向content scripts发送消息
chrome.tabs.sendMessage(tab.id, message, (res) => {
srcList = Array.from(new Set(res));
// popup中展示图片
const imgList = srcList.map((src) => `<img src="${src}" />`).join('');
document.getElementById('app').innerHTML = imgList;
});
});
});
const saveImageBtn = document.getElementById('save');
saveImageBtn.addEventListener('click', () => {
// 保存图片
});
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<style>
body,
img {
width: 400px;
}
</style>
</head>
<body>
<button id="get">获取</button>
<button id="save">保存</button>
<div id="app"></div>
<script src="./js/popup.js"></script>
</body>
</html>
这里我们需要注意,插件要想和当前活动页面通信就需要首先获取它的tabId,而要获取当前活动页面的tabId则需要给予插件对应的权限,因此我们需要在manifest.json中声明所需要的权限。
{
...
"permissions": [
"activeTab"
]
}
完成后更新一下插件,然后打开想要获取图片的页面点击获取按钮即可(如果页面已经提前打开请刷新一下)
保存图片
js可以通过a标签设置href和download属性来实现批量保存图片,但是这里我们要通过调用chrome的download API来实现。
...
saveImageBtn.addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, ([tab]) => {
if (!srcList) {
document.getElementById('app').innerHTML = '未获取图片';
return;
}
srcList.forEach((src) => {
chrome.downloads.download({
url: src,
});
});
});
});
与获取活动页面相同,download API同样也需要获取权限
{
...
"permissions": [
"activeTab",
"downloads"
]
}
这样一个获取当前页面图片的插件就完成了。
参考文章
Chrome插件开发入门的更多相关文章
- Chrome插件开发入门(二)——消息传递机制
Chrome插件开发入门(二)——消息传递机制 由于插件的js运行环境有区别,所以消息传递机制是一个重要内容.阅读了很多博文,大家已经说得很清楚了,直接转一篇@姬小光 的博文,总结的挺好.后面附一 ...
- [Chrome插件开发]001.入门
Chrome插件开发入门 Chrome扩展文件 Browser Actions(扩展图标) Page Actions(地址栏图标) popup弹出窗口 Background Pages后台页面 实战讲 ...
- vue.js 初体验— Chrome 插件开发实录
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:陈纬杰 背景 对于经常和动画开发打交道的开发者对于Animate.css这个动画库不会陌生,它把一些常见 ...
- chrome插件开发-消息机制中的bug与解决方案
序言 最近开发chrome插件,涉及到消息传递机时按照教程去敲代码,结果总是不对.研究了大半天终于找到原因,现在记录下. 程序 插件程序参考官网 chrome官网之消息传递机制, 不能FQ的同事也可以 ...
- Chrome插件开发,美化网页上的文件列表。chrome-extension,background
上一篇文章 通过“content-scripts”的方式向页面注入js和css来美化页面,但是有一个弊端:一旦配置好需要注入的页面,之后如果这个页面地址以后发生变化,或者要新加一些URL进来,那么得修 ...
- Chrome插件开发,美化网页上的文件列表。chrome-extension,content-scripts
趁着2018年还剩最后几天,发几篇博客,荒废太久了,惭愧. 最近也是需求驱动,研究了下Chrome插件开发.来看一下我们公司运维提供的日志查看页面 所有项目的日志都参杂在一起,每次去找都很痛苦.慢慢发 ...
- chrome插件开发学习(一)
两个不错的网址: 360chrome插件开发文档:http://open.chrome.360.cn/extension_dev/manifest.html 图灵 chrome插件开发于应用 电子书: ...
- 入门chrome插件开发教程和经验总结,一篇就搞掂!
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_44244857/articl ...
- Vue插件开发入门
相对组件来说,Vue 的插件开发受到的关注要少一点.但是插件的功能是十分强大的,能够完成许多 Vue 框架本身不具备的功能. 大家一般习惯直接调用现成的插件,比如官方推荐的 vue-router.vu ...
随机推荐
- [转]ROS Q&A | How to read LaserScan data
http://www.theconstructsim.com/read-laserscan-data/ Step 1. Open a project on ROS Development Studio ...
- 在测试自定义starter时,若出现无法找到helloservice的Bean的解决方法
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoc ...
- nginx日志文件切分
定义cut_nginx_log.sh 日志文件脚本如下 #!/bin/bash#LOGS_PATH为日志存放路径LOGS_PATH=/weblog/nginx/logsYESTERDAY=$(date ...
- 用OkHttpGo和FastJson获取OneNET云平台数据(解析嵌套数组)
JSON数据格式有两种,一种是 { } 大括号表示的JSON对象,一种是 [ ] 中括号表示的JSON数组.从OneNET获取到的数组是这样的,并用Json解析网址查看https://jsonform ...
- Dockerfile怎么用
目录 Docker的Dockerfile 1.常用命令 2.使用Dockerfile创建镜像 Docker的Dockerfile Dockerfile是由一系列命令和参数构成的脚本文件,这些命令应用于 ...
- 生产者与消费者以及ActiveMQ
生产者与消费者以及ActiveMQ 一. 多线程实现生产者与消费者 1.1 生产者与消费者头文件 #pragma once #include <iostream> #include < ...
- Python列表元组和字典解析式
目录 列表解析式List comprehensive 集合解析式Set comprehensive 字典解析式Dict comprehensive 总结 以下内容基于Python 3x 列表解析式Li ...
- sitemesh简单介绍
SiteMesh 是一个网页布局和修饰的框架,利用它可以将网页的内容和页面结构分离,以达到页面结构共享的目的. Sitemesh是由一个基于Web页面布局.装饰以及与现存Web应用整合的框架. 它能帮 ...
- c++ 反汇编 局部静态变量
vs2017下测试 34: for (int i = 0; i < 5; i++) 0029734E C7 45 F8 00 00 00 00 mov dword ptr [ebp-8],0 0 ...
- python3 中is和==的区别
is 身份运算符,用来判断对象是否属于同一地址 (python内置函数id() 可以返回对象地址) == 比较运算符,用于判断值是否相同