本人是一个web前端开发工程师,主要是vue框架,整理了一些Chrome扩展,今后也会一直更新,有好建议的同学欢迎评论区分享讨论 ;-)
序号 | 文章 |
---|---|
1 | 浏览器扩展安装 |
2 | 浏览器扩展(代码注入)简易DEMO |
3 | 浏览器扩展(代码注入)较完善脚手架 |
4 | Vue版本浏览器扩展(代码注入)最终版框架 |
5 | 较完善脚手架版本源码 |
6 | Vue版本源码 |
7 | 扩展中共享数据-chrome.storage.sync.xxx |
前言
有一个需求,需要从options_page页面中保存数据到本地,供content_script使用,已验证可以实现。popup以及devtools_page页面应该也是可以的,后期继续测试~~~
共享数据之options_page创建数据,devtools pannel、popup、options、content_script 能够读取
原理
chrome.storage.sync 是 Chrome 浏览器提供的 API,用于在 Chrome 扩展程序中进行数据存储和同步。通过 chrome.storage.sync API,开发者可以方便地将数据存储在用户的 Chrome 浏览器账号中,并且在用户登录到其他设备时自动同步这些数据。
使用 chrome.storage.sync API 可以帮助开发者实现跨设备的数据同步功能,让用户在不同的设备上都能访问到相同的数据。这对于需要在多个设备上保持数据同步的应用或扩展程序非常有用。同时, chrome.storage.sync API 还提供了简单的方法来存储和检索数据,使开发过程更加便捷。
基本使用
要使用 chrome.storage.sync 来在Chrome扩展程序中保存和检索数据,可以按照以下步骤进行:
0. 配置manifest.json 文件
在扩展程序的代码中,首先确保已经申明了 “permissions”: [“storage”] 权限。
1. 保存
使用 chrome.storage.sync.set() 方法来保存数据到同步存储中。
chrome.storage.sync.set({key: value}, function() {
console.log('Value is set to ' + value);
});
2. 读取
使用 chrome.storage.sync.get() 方法来从同步存储中检索数据。
chrome.storage.sync.get('key', function(data) {
console.log('Value currently is ' + data.key);
});
这里需要注意,获取的data是全局的数据,需要data.key~~~
3. 监听
如果需要监听存储区域的更改,可以使用 chrome.storage.onChanged 事件监听器。
chrome.storage.onChanged.addListener(function(changes, namespace) {
for (var key in changes) {
var storageChange = changes[key];
console.log('Storage key "%s" in namespace "%s" changed. ' +
'Old value was "%s", new value is "%s".',
key,
namespace,
storageChange.oldValue,
storageChange.newValue);
}
});
通过这些方法,你可以在Chrome扩展程序中使用 chrome.storage.sync 来保存和检索数据,并且在数据发生更改时进行相应的处理。
进阶:场景升级
能否将该chrome.storage.sync 封装成可以保存以数据库表维度进行维护呢。
使用示例
例如:用户页面userPage,表中有字段id、name、age…
封装好参数:
- pageName:表名,必填写!
- body:需要保存的结构体,表中的一条数据
- body.id: 表中数据的唯一标识
对于请求列表这边的参数略微不同,多添加了几个:
1. 新增
saveItem({
pageName: 'userPage',
body: {name:"penk1",age:"33"}
});
默认保存成功,并且id:1
2. 修改
假设已经userPage表中已经有id为1的数据,怎么会新增
saveItem({
pageName: 'userPage',
body: {id:1,name:"penk1",age:"333"}
});
3. 删除
deleteItem({
pageName: 'userPage',
id:1
});
4. 查询
getList({
pageName: 'userPage',
body:{id:1},
pageNum: 1,
pageSize: 10,
});
代码封装
只是一个简易版的,并不能实现去重以及暂时未添加翻页
// 查询
export const getList = getListFn;
// 新增跟修改
export const saveItem = saveItemFn;
// 删除
export const deleteItem = deleteItemFn;
// ==========================增删改查=============================
// 增改同个接口,根据ID来判断~
async function saveItemFn(params) {
try {
if (params.body.id) {
await editItemFn(params);
} else {
await addItemFn(params);
}
return {
result: true,
};
} catch (error) {
return {
result: false,
message: error.message,
};
}
}
// 查询项
async function getListFn({
pageName,
isAll,
pageNum = 0,
pageSize = 10,
...body
}) {
let data = [];
try {
data = await getStorage(pageName);
let total = data.length;
if (isAll) {
return {
result: true,
data,
total,
};
}
let keys = Object.keys(body);
let targetData = data.filter(item => {
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
// 如果搜索项为null,则判断下一个
if (!body[key]) {
continue;
}
if (item[key] !== body[key]) {
return false;
}
}
return true;
});
if (typeof pageNum !== 'undefined' && pageSize && pageNum > 0) {
targetData = targetData.splice(pageSize * (pageNum - 1), pageSize);
}
return {
result: true,
data: targetData,
total,
};
} catch (error) {
return {
result: false,
message: error.message,
data,
};
}
}
// 添加项
async function addItemFn({ pageName, body }) {
let res = await getListFn({ pageName, isAll: true });
let data = [];
if (res.result) {
data = res.data;
}
data.push({ ...body, id: getUUID() });
await setStorage(pageName, data);
}
// 编辑项
async function editItemFn({ pageName, body }) {
let res = await getListFn({ pageName, isAll: true });
let data = [];
if (res.result) {
data = res.data;
}
let { item, index } = findItemById(data, body.id);
data[index] = body;
await setStorage(pageName, data);
}
// 删除项
async function deleteItemFn({ pageName, id }) {
try {
let res = await getListFn({ pageName, isAll: true });
let data = [];
if (res.result) {
data = res.data;
}
let { item, index } = findItemById(data, id);
data.splice(index, 1);
await setStorage(pageName, data);
return {
result: true,
};
} catch (error) {
return {
result: false,
message: error.message,
};
}
}
// ==========================封装方法=============================
// 根据id获取item
function findItemById(arr, targetId) {
for (let i = 0; i < arr.length; i++) {
if (arr[i].id === targetId) {
return { item: arr[i], index: i };
}
}
return { item: null, index: -1 };
}
// 获取key
function getStorage(key) {
return new Promise((resolve, reject) => {
// eslint-disable-next-line no-undef
chrome.storage.sync.get(key, function (data) {
try {
let obj = JSON.parse(data[key]);
resolve(obj);
} catch (error) {
console.log(key, data);
console.error(error);
resolve([]);
}
});
});
}
// 设置key
function setStorage(key, val) {
return new Promise((resolve, reject) => {
let t = null;
try {
if (typeof val === 'object') {
t = JSON.stringify(val);
}
} catch (error) {
console.log(key, val);
console.error(error.message);
t = val;
}
// eslint-disable-next-line no-undef
chrome.storage.sync.set({ [key]: t }, function () {
try {
resolve(t);
} catch (error) {
reject(error);
}
});
});
}
// 设置UUID
function getUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(
/[xy]/g,
function (c) {
const r = (Math.random() * 16) | 0;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
}
);
}
// 加密函数
function encrypt(str, shift = 6, numberShift = 3) {
let encrypted = '';
for (let i = 0; i < str.length; i++) {
let charCode = str.charCodeAt(i);
if (charCode >= 65 && charCode <= 90) {
// 大写字母
charCode = ((charCode - 65 + shift) % 26) + 65;
} else if (charCode >= 97 && charCode <= 122) {
// 小写字母
charCode = ((charCode - 97 + shift) % 26) + 97;
} else if (charCode >= 48 && charCode <= 57) {
// 数字
charCode = ((charCode - 48 - numberShift + 10) % 10) + 48;
}
encrypted += String.fromCharCode(charCode);
}
return encrypted;
}
// 解密函数
function decrypt(str, shift = 6, numberShift = 3) {
let decrypted = '';
for (let i = 0; i < str.length; i++) {
let charCode = str.charCodeAt(i);
if (charCode >= 65 && charCode <= 90) {
// 大写字母
charCode = ((charCode - 65 - shift + 26) % 26) + 65;
} else if (charCode >= 97 && charCode <= 122) {
// 小写字母
charCode = ((charCode - 97 - shift + 26) % 26) + 97;
} else if (charCode >= 48 && charCode <= 57) {
// 数字
charCode = ((charCode - 48 + numberShift) % 10) + 48;
}
decrypted += String.fromCharCode(charCode);
}
return decrypted;
}