赵宇博的技术博客 赵宇博的技术博客
首页
前端
后端
数据库专栏
k8s专栏
分布式专栏
Linux网络专栏
手写系列专栏
随笔
关于
GitHub (opens new window)
首页
前端
后端
数据库专栏
k8s专栏
分布式专栏
Linux网络专栏
手写系列专栏
随笔
关于
GitHub (opens new window)
  • Vue专栏

    • VUE-概述
    • Vuex
  • Chrome 扩展插件开发
    • 1、基础介绍
      • 1.1 基础结构
      • 1.2 声明browser_action
      • 1.3 commands 快捷键
    • 2、background scripts
    • 3、UI界面
      • 3.1 、popup.html
      • 3.2 popup.js
    • 4、扩展存储API
      • 4.1、chrome扩展自身的localStorage
      • 4.2、chrome扩展存储API
    • 5、用户选项页面 (option)
    • 6、书签管理
      • 1、获取所有书签信息
      • 2、获取某个节点的子树
      • 3、获取节点信息
      • 4、获取所有的子节点
      • 5、获取最近的书签
      • 6、搜索书签
      • 7、创建书签
      • 8、移动书签
      • 9、更新书签
      • 10、删除书签或者空书签文件夹
      • 11、删除整个书签树
  • 防抖与节流函数
  • 前端
zhaoyb
2023-12-04
目录

Chrome 扩展插件开发

# Chrome 扩展插件开发

# 1、基础介绍

扩展程序是定制浏览体验的小型软件程序。这些扩展程序能够使得用户根据个人需求或者偏好定制 Chrome 功能和行为。基于 HTML, JavaScript和 CSS 等 Web 技术构建。

扩展程序由不同的组件构成,这些组件包含以下几种:

  • background scripts (运行在后台的脚本)
  • content scripts (运行在页面的逻辑脚本)
  • options page (页面)
  • ui elements (UI元素)
  • 各种逻辑组件

# 1.1 基础结构

Chrome 的扩展程序必须有一个manifest.json文件,文件用来描述APP信息以及其他资源加载路径,需要最基本的四个信息就可以实现一个hello-word扩展插件

manifest.json

{
    "name":"hello-word",
    "description":"你好,扩展插件",
    "version":"1.0",
    "manifest_version":2
}
1
2
3
4
5
6
7
8

浏览器加载已解压的扩展程序,如图所示,已经完成了一个最基础的扩展插件

image-20220216184229154

# 1.2 声明browser_action

  • popup

    "default_popup":"popup.html"

    在点击插件的时候会弹出弹框,弹框内容就是popup.html的内容,popup的内容在点击浏览器空白处会自动关闭

    image-20220216185421661

  • icon

    "default_icon":"hello.png"

    插件展示的默认图标

# 1.3 commands 快捷键

commands属性用来配置快捷键 ,例如可以配置快捷键来直接唤醒程序,

{
 "commands":{
     "_execute_browser_action":{ //用来执行browser_action中的设置
         "suggested_key":{
             "default":"Ctrl+Shift+F", //默认win快捷键
             "mac":"MacCtrl+Shift+F"
         },
         "description":"打开popup.html"
     }
 }
}
1
2
3
4
5
6
7
8
9
10
11

# 2、background scripts

使用流程:

1、需要在maniifest.json文件中声明,使用background api

{
 "background":{
     "scripts":["background.js"],
     "persistent":false  
 }
}
1
2
3
4
5
6

2、扩展程序一旦安装,会自动加载scripts标签定义的所有脚本,并查找需要监听的重要的事件,

例如:脚本文件中需要持久化变量信息,使用runtime.onInstalled的侦听事件,在onInstalled监听事件中,脚本使用chrome的存储API设置一个value,后续所有的扩展程序组件都可以访问或者修改这个value

chrome.runtime.onInstalled.addListener(() => {
 chrome.storage.sync.set({color:'red'},() =>{
     console.log('color is red');
 });
});
1
2
3
4
5

3、由于上述脚本使用了storage权限,在扩展插件开发中,涉及到API的使用,必须要提前声明,需要在permissions字段注册才能使用。

{
 "permissions":["storage"],
}
1
2
3

代码示例:

//manifest.json
{
 "name":"hello-word",
 "description":"你好,扩展插件",
 "version":"1.0",
 "manifest_version":2,
	"browser_action":{
		"default_popup":"popup.html"
	},
	 "commands":{
     "_execute_browser_action":{
         "suggested_key":{
             "default":"Ctrl+Shift+F",
             "mac":"MacCtrl+Shift+F"
         },
         "description":"打开popup.html"
     }
 },
	"permissions":["storage"],
	"background":{
		"scripts":["background.js"],
		"persistent":false
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// background.js
chrome.runtime.onInstalled.addListener(() => {
 chrome.storage.sync.set({color:'red'},() =>{
     console.log('color is red');
 });
});
1
2
3
4
5
6

image-20220217100521607

# 3、UI界面

UI界面主要有两个,browser_action 和page_action,使用的时候两个选择一个,不可以同时使用,

主要区别:

browser_action 提供的功能面向全部网站,插件图标一直是激活的状态

page_action只针对对应网站提供的功能,插件需要配置激活规则,只有满足条件的网站才能使用插件,否则插件一直是灰色状态

# 3.1 、popup.html

在点击插件的时候会弹出弹框,弹框内容就是popup.html的内容,popup的内容在点击浏览器空白处会自动关闭

popup.html与普通html页面的区别就是不能使用内联script

# 3.2 popup.js

实战:使用脚本控制当前页面的背景色

popup.js

const changeColor = document.getElementById("changeColor");

changeColor.onclick = (element) =>{
	chrome.storage.sync.get('color',(data) =>{
		chrome.tabs.query({active:true, currentWindow: true},(tabs) =>{
			chrome.tabs.executeScript(
				tabs[0].id,
				{code: `document.body.style.backgroundColor="${data.color}"`}
			)
		});
	});
};
1
2
3
4
5
6
7
8
9
10
11
12

# 4、扩展存储API

存储数据分为三类

1、浏览器本身的localStorage(HTML5特性)

2、chrome扩展自身的localStorage,需要注意content_script中的localStorage是存储在对应域名下的,别的域名不能访问,而background_script的localStorage是存储在chrome扩展下的,所有域名都可以访问,所以一般都会在background_script中存储公共信息,供所有页面使用。

3、chrome扩展的存储API(需要声明storage权限)

# 4.1、chrome扩展自身的localStorage

1、localStorage属于key/value存储类型,如果想要存储对象格式 ,就必须以json字符的格式来存储,后续再处理解析

2、API

//增加
localStorage.name = 'zhangsan'; || localStorage['name'] = 'zhangsan';
//修改
localStorage.name = 'lisi'; || localStorage['name'] = 'lisi';
//删除
localStorage.name = null; ||localStorage['name'] = null; 
//删除所有
localStorage.clear();
//查看
var name = localStorage.name; || var name = localStorage['name'];
1
2
3
4
5
6
7
8
9
10

# 4.2、chrome扩展存储API

1、可以看作是对localStorage的改进,可以将保存的数据写入本地磁盘,使用之前需要先声明storage权限

(数据存储目录:C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Local Extension Settings\扩展id)

存储分为两种方式:sync和local,唯一的区别就是sync会开启当前用户的数据同步功能(不过由于墙的问题,大多数用户无法登录谷歌账户,也就不存在同步需求了)

2、API

//sync添加
chrome.storage.sync.set({key:value},()=>{
 //添加成功
});
//local添加
chrome.storage.local.set({key:value},()=>{
 //添加成功
});

//sync读取
chrome.storage.sync.get(['key'],(data)=>{
 console.log(data.key);
});
//local读取
chrome.storage.local.get(['key'],(data)=>{
 console.log(data.key);
});

//获取一个或多个数据所占用的总空间 getBytesInUse
chrome.storage.sync.getBytesInUse(keys,(byts)=>{
 console.log(byts);
})
chrome.storage.local.getBytesInUse(keys,(byts)=>{
 console.log(byts);
})
此处的 keys 只能为 null、字符串或包含多个字符串的数组

//删除数据 remove
chrome.storage.sync.remove(keys,()=>{
 //删除成功
})
chrome.storage.local.remove(keys,()=>{
 //删除成功
})
keys 可以是字符串,也可以是包含多个字符串的数组

//删除所有数据 clear
chrome.storage.sync.clear(()=>{
 //删除成功
})
chrome.storage.local.clear(()=>{
 //删除成功
})

//监听事件 onChange 当存储区的数据发生改变时,触发此方法
chrome.storage.onChaged.addListener((changes,storageArea)=>{
 //callback() 会接收到两个参数,第一个为 changes,第二个是 StorageArea。changes 是词典对象,键为更改的属性名称,值包含两个属性,分别为 oldValue 和 newValue;StorageArea 为 local 或 sync。
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

# 5、用户选项页面 (option)

# 6、书签管理

使用 chrome.bookmarks 能够创建、组织和操作书签,能够自定义操作书签的页面

需要申请权限 [bookmarks]

注意:无法使用 chrome.bookmarks API 添加或删除根文件夹中的条目。无法重命名、移动或删除特殊的 “书签栏” 和 “其他” 文件夹。

# 1、获取所有书签信息

chrome.bookmarks.getTree(function callback)

chrome.bookmarks.getTree((res) => {
        console.log(res);
})
1
2
3

返回数据示例:

image-20220419192054877

image-20220419191620338

通过这个方法能够拿到整个书签栏的树,而最外层就是根节点,根节点没有 title,根节点的两个子节点就是 书签栏和其他书签两个,id 分别是 1 和 2

# 2、获取某个节点的子树

chrome.bookmarks.getSubTree(string id, function callback)

chrome.bookmarks.getSubTree(tree[0].children[0].children[0].id, (res) => {
   console.log(res);
})
`getSubTree(id) 需要传递id参数`
1
2
3
4

image-20220420133825874

# 3、获取节点信息

chrome.bookmarks.get(string or array of string idOrIdList, function callback)

需要注意的是,无论是什么 get 方法,每次都是返回一个 Array 类型,即使请求的是节点,返回的也是 Array,并且不会返回子节点信息

get.onclick = (element) =>{
	chrome.bookmarks.get('50', (res) => {
	   console.log(res);
	})
}
1
2
3
4
5

image-20220420134321289

# 4、获取所有的子节点

chrome.bookmarks.getChildren(string id, function callback)

getChildren.onclick = (element) =>{
        chrome.bookmarks.getChildren('50', (res) => {
           console.log(res);
        })
}
1
2
3
4
5

image-20220420134745826

# 5、获取最近的书签

chrome.bookmarks.getRecent(integer numberOfItems, function callback)

//返回最近创建的 3 个页签
getRecent.onclick = () => {
    chrome.bookmarks.getRecent(3, (res) => {
        console.log(res);
    })
};
1
2
3
4
5
6

image-20220420135039546

# 6、搜索书签

chrome.bookmarks.search(string or object query, function callback)

根据title和url属性进行不区分大小写的模糊匹配搜索页签节点数据

<div class="col-md-12">
    <textarea id="title" cols="30" rows="1">github</textarea>
	<button id="search" class="btn btn-primary">search</button>
</div>

search.onclick = (element) =>{
	const title = document.getElementById("title").value;
	chrome.bookmarks.search(title, (res) => {
	   console.log(res);
	})
}
1
2
3
4
5
6
7
8
9
10
11

image-20220420144805775

# 7、创建书签

chrome.bookmarks.create(object bookmark, function callback)

创建一个书签,在指定的 parentId 下创建书签或文件夹。如果 url 为NULL或没有该字段,会创建一个文件夹。

如果parentId 为1,则可以在根节点创建书签或文件夹

<div class="col-md-12">
    创建书签
父书签名:<textarea id="pTitle" cols="30" rows="1">父书签名</textarea>
新书签名:<textarea id="newTitle" cols="30" rows="1">新书签名</textarea>
新书签地址:<textarea id="newUrl" cols="30" rows="1">新书签地址</textarea>
<button id="addBookmark" class="btn btn-primary">添加书签</button>
</div>
<div class="col-md-12">
    根节点创建书签
新书签名:<textarea id="newTitle1" cols="30" rows="1">新书签名</textarea>
新书签地址:<textarea id="newUrl1" cols="30" rows="1">新书签地址</textarea>
<button id="addBookmark1" class="btn btn-primary">添加书签</button>
</div>

addBookmark.onclick = (element) =>{
	const pTitle = document.getElementById("pTitle").value;
	const newTitle = document.getElementById("newTitle").value;
	const newUrl = document.getElementById("newUrl").value;
	let obj
	chrome.bookmarks.search(pTitle, (res) => {
	   obj = {
		   parentId:res[0]['id'],
		   title:newTitle,
		   url:newUrl
	   }
	   chrome.bookmarks.create(obj, (res) => {
			console.log(res);
		})
	})
}
addBookmark1.onclick = (element) =>{
	const newTitle1 = document.getElementById("newTitle1").value;
	const newUrl1 = document.getElementById("newUrl1").value;
	let obj
	chrome.bookmarks.search(pTitle, (res) => {
	   obj = {
		   parentId:'1',
		   title:newTitle1,
		   url:newUrl1
	   }
	   chrome.bookmarks.create(obj, (res) => {
			console.log(res);
		})
	})
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 8、移动书签

chrome.bookmarks.move(string id, object destination, function callback)

//把id为10的页签移动到id为1的节点下面
move.onclick = (element) =>{
	const obj ={
		parentId: '1' 
	}
	chrome.bookmarks.move('10',obj, (res) => {
	   console.log(res);
	})
}
1
2
3
4
5
6
7
8
9

# 9、更新书签

chrome.bookmarks.update(string id, object changes, function callback)

目前只支持更新title和url

//把书签id为8的title改为百度1
update.onclick = (element) =>{
	const obj ={
		title: '百度1'
	}
	chrome.bookmarks.update('8',obj, (res) => {
	   console.log(res);
	})
}

1
2
3
4
5
6
7
8
9
10

# 10、删除书签或者空书签文件夹

chrome.bookmarks.remove(string id, function callback)

只能删除单个书签或者空文件夹,如果不是空文件夹则会报错Can't remove non-empty folder (use recursive to force).

remove.onclick = (element) =>{
	chrome.bookmarks.remove('272', (res) => {
	   console.log(res);
	})
}
1
2
3
4
5

# 11、删除整个书签树

chrome.bookmarks.removeTree(string id, function callback)

可以删除当前书签和书签文件夹的子节点

removeTree.onclick = (element) =>{
	chrome.bookmarks.removeTree('272', (res) => {
	   console.log(res);
	})
}
1
2
3
4
5
#Chrome
上次更新: 2024/01/11, 16:22:43
Vuex
防抖与节流函数

← Vuex 防抖与节流函数→

最近更新
01
Activiti6-业务实现
12-06
02
Activiti6-API详解
11-28
03
SpringBoot集成Activiti和UI
11-21
更多文章>
Theme by Vdoing | Copyright © 2022-2024 赵宇博 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式