Chrome扩展框架- 共享数据之options_page创建数据,其他页面devtools pannel、popup、options、content_script 能够读取

本人是一个web前端开发工程师,主要是vue框架,整理了一些Chrome扩展,今后也会一直更新,有好建议的同学欢迎评论区分享讨论 ;-)

序号文章
1浏览器扩展安装
2浏览器扩展(代码注入)简易DEMO
3浏览器扩展(代码注入)较完善脚手架
4Vue版本浏览器扩展(代码注入)最终版框架
5较完善脚手架版本源码
6Vue版本源码
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…

封装好参数:

  1. pageName:表名,必填写!
  2. body:需要保存的结构体,表中的一条数据
  3. 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;
}

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Penk是个码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值