localStorage的高阶用法

2023-11-09

原文:https://mp.weixin.qq.com/s/VBTAWVMAUq822dwNA1A2kg


const config = {
    type: 'localStorage', // 本地存储类型 localStorage/sessionStorage
    prefix: 'SDF_0.0.1', // 名称前缀 建议:项目名 + 项目版本
    expire: 1, //过期时间 单位:秒
    isEncrypt: true // 默认加密 为了调试方便, 开发过程中可以不加密
}

/**
 * title: storage.js
 * Desc: 对存储的简单封装
 * import {isSupportStorage, hasStorage, setStorage,getStorage,getStorageKeys,getStorageForIndex,getStorageLength,removeStorage,getStorageAll,clearStorage} from '@/utils/storage'
 * 安装crypto-js
 * npm install crypto-js
 * 引入 crypto-js 有以下两种方式
 * import CryptoJS from "crypto-js"; 或者 const CryptoJS = require("crypto-js");
 */

import CryptoJS from 'crypto-js';

// 十六位十六进制数作为密钥
const SECRET_KEY = CryptoJS.enc.Utf8.parse("3333e6e143439161");
// 十六位十六进制数作为密钥偏移量
const SECRET_IV = CryptoJS.enc.Utf8.parse("e3bbe7e3ba84431a");

// 类型 window.localStorage,window.sessionStorage,
const config = {
	type: 'localStorage', // 本地存储类型 sessionStorage
	prefix: 'SDF_0.0.1', // 名称前缀 建议:项目名 + 项目版本
	expire: 1, //过期时间 单位:秒
	isEncrypt: true // 默认加密 为了调试方便, 开发过程中可以不加密
}

// 判断是否支持 Storage
export const isSupportStorage = () => {
	return (typeof(Storage) !== "undefined") ? true : false
}

// 设置 setStorage
export const setStorage = (key, value, expire = 0) => {
	if (value === '' || value === null || value === undefined) {
		value = null;
	}

	if (isNaN(expire) || expire < 0) throw new Error("Expire must be a number");

	expire = (expire ? expire : config.expire) * 1000;
	let data = {
		value: value, // 存储值
		time: Date.now(), //存值时间戳
		expire: expire // 过期时间
	}

	const encryptString = config.isEncrypt ?
		encrypt(JSON.stringify(data)) :
		JSON.stringify(data);

	window[config.type].setItem(autoAddPrefix(key), encryptString);
}

// 获取 getStorage
export const getStorage = (key) => {
	key = autoAddPrefix(key);
	// key 不存在判断
	if (!window[config.type].getItem(key) || JSON.stringify(window[config.type].getItem(key)) === 'null') {
		return null;
	}

	// 优化 持续使用中续期
	const storage = config.isEncrypt ?
		JSON.parse(decrypt(window[config.type].getItem(key))) :
		JSON.parse(window[config.type].getItem(key));

	let nowTime = Date.now();

	// 过期删除
	if (storage.expire && config.expire * 6000 < (nowTime - storage.time)) {
		removeStorage(key);
		return null;
	} else {
		// 未过期期间被调用 则自动续期 进行保活
		setStorage(autoRemovePrefix(key), storage.value);
		return storage.value;
	}
}

// 是否存在 hasStorage
export const hasStorage = (key) => {
	key = autoAddPrefix(key);
	let arr = getStorageAll().filter((item) => {
		return item.key === key;
	})
	return arr.length ? true : false;
}

// 获取所有key
export const getStorageKeys = () => {
	let items = getStorageAll()
	let keys = []
	for (let index = 0; index < items.length; index++) {
		keys.push(items[index].key)
	}
	return keys
}

// 根据索引获取key
export const getStorageForIndex = (index) => {
	return window[config.type].key(index)
}

// 获取localStorage长度
export const getStorageLength = () => {
	return window[config.type].length
}

// 获取全部 getAllStorage
export const getStorageAll = () => {
	let len = window[config.type].length // 获取长度
	let arr = new Array() // 定义数据集
	for (let i = 0; i < len; i++) {
		// 获取key 索引从0开始
		let getKey = window[config.type].key(i)
		// 获取key对应的值
		let getVal = window[config.type].getItem(getKey)
		// 放进数组
		arr[i] = {
			'key': getKey,
			'val': getVal,
		}
	}
	return arr
}

// 删除 removeStorage
export const removeStorage = (key) => {
	window[config.type].removeItem(autoAddPrefix(key));
}

// 清空 clearStorage
export const clearStorage = () => {
	window[config.type].clear();
}

// 名称前自动添加前缀
const autoAddPrefix = (key) => {
	const prefix = config.prefix ? config.prefix + '_' : '';
	return prefix + key;
}

// 移除已添加的前缀
const autoRemovePrefix = (key) => {
	const len = config.prefix ? config.prefix.length + 1 : '';
	return key.substr(len)
	// const prefix = config.prefix ? config.prefix + '_' : '';
	// return  prefix + key;
}

/**
 * 加密方法
 * @param data
 * @returns {string}
 */
const encrypt = (data) => {
	if (typeof data === "object") {
		try {
			data = JSON.stringify(data);
		} catch (error) {
			console.log("encrypt error:", error);
		}
	}
	const dataHex = CryptoJS.enc.Utf8.parse(data);
	const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {
		iv: SECRET_IV,
		mode: CryptoJS.mode.CBC,
		padding: CryptoJS.pad.Pkcs7
	});
	return encrypted.ciphertext.toString();
}

/**
 * 解密方法
 * @param data
 * @returns {string}
 */
const decrypt = (data) => {
	const encryptedHexStr = CryptoJS.enc.Hex.parse(data);
	const str = CryptoJS.enc.Base64.stringify(encryptedHexStr);
	const decrypt = CryptoJS.AES.decrypt(str, SECRET_KEY, {
		iv: SECRET_IV,
		mode: CryptoJS.mode.CBC,
		padding: CryptoJS.pad.Pkcs7
	});
	const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8);
	return decryptedStr.toString();
}


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

localStorage的高阶用法 的相关文章

  • 如何通过 JSON / JS 在 Jenkins 中添加 CSRF 面包屑

    我想在 Jenkins 中通过 API 创建作业 但无法连接 Jenkins 中的 CSRF 保护课程 我得到了一个面包屑 但不知道如何将其附加到 JSON 或 JavaScript 中的 url 请求 以通过 POST 方法获取数据传递
  • 如何为现代 C++ 迭代 JSON 中的 JSON

    我想迭代 json 对象中的每个条目 但我收到一个又一个难以理解的错误 下面的例子如何改正 include
  • 从 Json 纯 JavaScript 创建表

    我有一个带有多个可以更改的键的 Json 如下所示 Var children num 6 name me phone 7 num 8 name him phone 9 我想要一个带有标题的表格 号码 姓名 电话 我怎样才能只用 JavaSc
  • Mongoose查询结果是只读的吗?

    如何修改 Mongoose 查询返回的对象 假设我们有以下模式 var S new mongoose Schema name String field String 我对结果进行了以下查询和修改 var retrieve function
  • 返回视图作为 JSON 对象的一部分

    我有一个应用程序只加载一次完整视图 我这样做的原因并不重要 重要的是 其余内容只会以部分视图的形式返回 除了一些内容之外 我还有一些 JSON 对象 我想通过每个 AJAX 请求在服务器之间来回传递 有没有办法返回一个 JSON 对象 并将
  • 后退按钮 (Chrome) 在 Play Framework 中获取 Json 而不是 HTML

    各位 我有一个 Web 应用程序 我在其中对同一资源的 JSON 和 HTML 表示重复使用了相同的路由 现在我们将其称为 foo details 该页面是从 bar details 链接的 因此 查看 bar details 您会看到链接
  • Elm:如何从 JSON API 解码数据

    我有这个数据使用http jsonapi org http jsonapi org format data type prospect id 1 attributes provider user id 1 provider facebook
  • mysql_query 保留返回时在表中创建的数据类型?

    我在mysql中有一个表 CREATE TABLE user id INT name VARCHAR 250 我查询表 result mysql query SELECT id name FROM user 我收集结果 while row
  • 通过 JSONP 通过 CDN 传输静态 JSON 文件

    我有大量 JSON 格式的静态 很少变化的数据 为了提高我的 ASP NET MVC 应用程序性能 我想将它们移动到 CDN Amazon Cloud Front 然而 当我这样做时 跨域策略启动 jQuery 进行 HTTP OPTION
  • JSON 转换带有整数键的 Map

    我有一个测试代码的小样本 我尝试将 Map 转换为 JSON 字符串并返回 在解析 JSON 字符串时 结果映射包含字符串键 1 而不是整数键 1 从而导致测试失败 用作此映射的键的 POJO 也会发生同样的情况 这是预期行为还是我省略了
  • 检索 Steam 市场上物品的价格历史记录

    关于 Steam 市场上的物品 我想知道是否有办法检索某物品在一段时间内的价格历史记录 我知道 Steam 为想要将市场特定数据集成到自己网站中的开发人员提供了一个特殊的 api 但我还没有找到任何有关以 json 形式检索商品价格历史记录
  • 在Python中,如何通过去掉括号和大括号来打印Json

    我想以一种很好的方式打印 Json 我想去掉方括号 引号和大括号 只使用缩进和行尾来显示 json 的结构 例如 如果我有一个像这样的 Json A A1 1 A2 2 B B1 B11 B111 1 B112 2 B12 B121 1
  • 使用 Jackson 删除 JSON 元素

    我有一个特定的 JSON 节点 对应于 import org codehaus jackson JsonNode 而不是 导入 org codehaus jackson map JsonNode givenName Jim formatte
  • 如何显示多维数组第二层的 json 值?

    解决此代码时遇到问题 这些是数组 Array 0 gt stdClass Object id gt 1 name gt delux price gt 213 description gt tv gt 0 breakfast gt 0 par
  • PHP:file_get_contents 与 json_decode 不能一起工作

    使用 file get contents 读取 json 文件后遇到问题 当我运行这段代码时 它工作正常
  • POST 表单数据为 application/json

    我正在开发一个 API 它接收 application json post 请求 并触发一些流程 我目前的主要问题是发送一个 application json 帖子 其中包含来自输 入表单的数据 我已经尝试过 jQuery ajax 但由于
  • 将 JSON 反序列化为自定义列表

    我有这个 json var x 99 abc 2dp GroupNum 0 Total 4 1 7 x date 60 x 1dp GroupNum 1 存在以下规则 让i参考内部列表索引 x i 0 必填项 始终为整数 x i 1 必填项
  • 如何按单个整数字段对 JSON 进行排序? [复制]

    这个问题在这里已经有答案了 我有以下 JSON title title order 0 order 9 order 2 JSON 包含很多字段 我如何根据字段对它们进行排序order field 我一直在寻找 Nodejs 中内置的东西 但
  • 如何强制控制器/操作使用 JsonValueProvider

    再会 我正在使用 ASP NET MVC 3 其中JsonValueProvider http haacked com archive 2010 04 15 sending json to an asp net mvc action met
  • json、rails、javascript 中的解析错误

    我需要将 ruby 数组放入 javascript 数组中 但出现解析错误 var characters 这就是我将 ruby 嵌入到内联 javascript 中的方式 但它出现了解析错误 我应该如何将此 ruby 数组放入 javasc

随机推荐

  • 跨域请求避免OPTIONS请求(预检请求)

    有时候前后端分离域名不一致 会造成跨域请求 而跨域请求有时候会自动发起两次请求 第一次为预检请求 即OPTIONS请求 一般来说使用 application json 的 post 请求是必然会带入OPTIONS请求 OPTIONS请求也被
  • flex布局中align-items 和align-content的区别

    参考资料 http stackoverflow com questions 31250174 css flexbox difference between align items and align content 看了很多翻译的技术文档
  • 王佩丰excel学习笔记(三):第七——十讲

    目录 第七讲 第八讲 第九讲 第十讲 第七讲 excel连接文本 各种基础运算 相对引用与绝对引用 利用 按F4可以快速加美元号 但我电脑不行 函数 sum average rank 要排谁 排名的区域 这节总体简单 第八讲 if 判断条件
  • 自动劫持root密码

    前言 1 暴力破解sshd服务密码 2 自动劫持root密码并转发密码到邮箱 实战 自动劫持root密码并转发密码到邮箱 1 自动劫持root密码 2 把存密码的文件转发到邮箱 上传软件 rz 0x06 openssh 5 9p1 patc
  • 学习笔记-Matlab算法篇-插值算法

    插值算法 01拉格朗日多项式插值 进而得到拉格朗日多项式 Matlab求解 matlab中没有自带的求解函数 需要自行实现 function f Language x y x0 syms t if length x length y n l
  • 《王道》数据结构之绪论(一)

    数据结构入门之绪论 一 大纲 一 数据结构 1 1 基本概念 1 2 数据结构三要素 1 2 1 逻辑结构 1 2 2 物理结构 1 2 3 数据运算 二 算法 2 1 基本概念 2 1 1 五个特性 2 1 2 优秀算法的标准 2 2 算
  • 高防服务器和高防CDN

    现如今无论是高防服务器还是高防CDN的应用都十分广泛 但是大家对高防服务器和 高防CDN的作用理解的都比较模糊 因为无论是百度还是论坛等地方搜索的话都会弹出一 大堆高防服务器和高防CDN的连接导致大家想了解高防服务器和高防CDN的欲望下降甚
  • java 打印map后的输出

    java 打印map后的输出 syso直接打印parameters map类型 输出 password Ljava lang String 1080882d username Ljava lang String 69504d30 表示一维数
  • QT 创建使用动态库

    一 创建并编译库 创建项目 选择Library下的C Library 2 选择shared library 3 此时创建的项目的 pro文件如下 QT gui TEMPLATE lib DEFINES Data LIBRARY DEFINE
  • 看看Android的触摸事件分发

    当我们的手指从触摸屏幕上的各种View 开始到这个点击事件的结束到底经历了什么 我们来简单分析下 之所以是简单分析 是因为这里完全不涉及hal层 事件类型 触摸事件会有三种类型 int action MotionEventCompat ge
  • 硬件设计——外围电路(晶振电路)

    硬件设计之晶振电路 为什么要用晶振 晶振电路由何组成 晶振电路中其电容的作用 在日常的电路设计中 我们经常会用到晶振电路 所以我们就要首先先提一下什么是晶振 这样才能理解晶振电路 为什么要用晶振 晶振的作用是为系统提供基本的时钟信号 通常一
  • 基于金融大数据的特征提取与趋势预测系统(一)2021-06-30

    项目分工和项目需求初步了解 在本项目的分工中我负责的是前端展示部分 前端展示的两个部分 1 登陆及注册 实现用户登陆本系统 以及注册成为用户的功能 以保证用户在使用本系统时的安全性 2 股票可视化模块 数据可视化主要旨在借助于图形化手段 清
  • TypeScript的数组和元组

    数组 在TypeScript中数组的定义与JavaScript中别无二致 但是JavaScript中的数组具有很大灵活性 即数组内可以存储任意类型数据 那么在TypeScript中能不能做到呢 答案是肯定的 const arr string
  • Java学习笔记17——多态与抽象

    多态与抽象 多态 多态是什么 多态的前提和体现 多态中成员访问的特点 多态的好处和弊端 多态中的转型 分类 抽象类 什么是抽象类 抽象的关键字 抽象类的特点 抽象类的成员特点 多态 多态是什么 多态是同一个对象 在不同时刻表现出来的不同形态
  • 【华为机试刷题笔记】HJ41-称砝码

    题目描述 现有n种砝码 重量互不相等 分别为 m1 m2 m3 mn 每种砝码对应的数量为 x1 x2 x3 xn 现在要用这些砝码去称物体的重量 放在同一侧 问能称出多少种不同的重量 注 称重重量包括 0 数据范围 每组输入数据满足 1
  • 自学Python爬虫学到什么程度?就可以去找工作了?

    确立目标 了解需求 首先我们要先定位自己的目标 当然我们先以爬虫工程师来做个说明 去招聘网上看看需求都有哪些 直接做个拉勾网爬虫 结果了 仔细看看 我们可以得出以下几点 1 python 不是唯一可以做爬虫的 很多语言都可以 尤其是 jav
  • 从零开发区块链应用(七)--gin框架参数获取

    文章目录 一 获取query参数 二 获取form表单参数 三 获取JSON参数 四 获取path参数 五 参数绑定 一 获取query参数 query指的是URL 后面携带的参数 例如user info username 张三 passw
  • 大白话Java版 TCP Socket编程案例 清晰明了

    最近学习网络的过程中 了解到了应用借助socket接口在tcp上建立连接 发送请求的过程 遂做个记录 文章目录 整体流程 服务端 1 创建套接字绑定端口 2 等待接收请求 4 获取请求 ConnectSocket建立 6 读请求并处理 8
  • TCP拥塞控制简单理解

    1 TCP的控制机制 序号 TCP通过序号可以实现一下几个功能 1 确认应答处理 发送端收到接收端的确认应答 可以得知某些数据包被接收端接收了 2 顺序控制 接收端可以利用序号对接收到的报文进行排序 3 重发控制 如果发送端没有收到确认应答
  • localStorage的高阶用法

    原文 https mp weixin qq com s VBTAWVMAUq822dwNA1A2kg const config type localStorage 本地存储类型 localStorage sessionStorage pre