木灵鱼儿
阅读:107
ts封装一个localStorage和sessionStorage的类
前言
希望存储一个对象的时候能自动JSON转成字符串,存储一个string类型的值时,不需要再JSON化了,不然又多两引号,和原生存储使用会有出入,我的宗旨就是能和原生效果保持一致的情况下增加一些方便的处理。
拿取的时候就会有一些顾虑了,因为拿到的值就是字符串类型,所以我加了一个额外的参数来判断是否需要JSON解析,默认是需要的,这个配置用于这个值我可能自己手动转成字符串存的,它的源值是一个对象,我不希望取值的时候被解析出来,我就要它原样给我,应对这种情况加了一个配置判定。
在拿取的时候返回的值类型是any,显然这不是我想要的,我希望能准确判定这个类型,于是通过泛型的方式进行约束。
另一个考量是我希望我的key在存储的时候能够特殊一点,不会与其他的存储混在一起,简单的办法就是加入前缀了,于是我加入了prefix
配置,本来我是希望这个配置设置后不为空字符串的,但是转念一想,有的时候我们可能就希望不要前缀,但是又能使用已封装的方法便捷性,于是允许了可以为空字符串。
源码
/** 存储类型 */
export type StorageType = "local" | "session";
/** 存储类配置参数 */
export type StorageOptions = {
type?: StorageType;
prefix?: string;
};
class JJStorage {
private storage: Storage;
private prefix: string = "";
constructor(options: StorageOptions) {
const { type, prefix } = options;
switch (type) {
case "local":
this.storage = window.localStorage;
break;
case "session":
this.storage = window.sessionStorage;
break;
default:
this.storage = window.localStorage;
}
if (prefix) {
this.prefix = prefix;
}
}
/** 存储数据 */
public setItem(key: string, value: any) {
key = this.prefix + key;
if (typeof value === "string") {
this.storage.setItem(key, value);
return;
}
try {
this.storage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error("存储数据失败:", error);
}
}
/** 获取数据 */
public getItem<T>(key: string, isJson: boolean = true) {
key = this.prefix + key;
const value = this.storage.getItem(key);
if (!value) return null;
if (!isJson) return value as T;
try {
return JSON.parse(value) as T;
} catch (error) {
return value as T;
}
}
/** 删除数据 */
public removeItem(key: string) {
key = this.prefix + key;
this.storage.removeItem(key);
}
/** 清空数据 */
public clear() {
this.storage.clear();
}
}
/** 实例化 */
const jjLocal = new JJStorage({ type: "local", prefix: "jj_" });
export { JJStorage, jjLocal };
版权申明
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿 - 有梦就能远航站点。未经许可,禁止转载。
相关推荐
ts实战:给没有类型声明的第三方库编写一个类型声明文件
前情提要在github找了一个原生代码写的Toast库,安装后发现没有ts类型声明,通过安装@types/库名 也没有现成的对应的类型声明库,于是想着自己写一份声明文件用,也是第一次,所以找了好些教程,这里做个笔记。npm仓库: Toastify说实话这个库不太行,不支持多个toast,权当练手了。类型声明文件在项目中,比如我是在src目录下创建一个types目录,专门存放这些类型声明文件,创建一个名为Toastify.d.ts的文件。内容如下:declare module "toastify" { /** toast定位 */ export type Toa...

利用发布订阅模式封装一个IntersectionObserver
前言用于判断当前元素是否出现在视口区域,以此来实现懒加载已经是日常业务必须的东西了,但是如何去判断这个元素是否出现在视口中,是一个非常头疼的地方。很久以前,我们通过dom.offsetTop的方式,不断的累加自身和父级元素的offsetTop值,得到元素具体文档顶部的距离,然后判断这个距离是否小于等于当前视窗的高度+滚动条scrollTop,如果是的话,说明用户已经滚动到了,或者滚过去了,这个时候就得触发图片懒加载。但是这种方式十分痛苦,需要递归计算offsetTop的值,而且性能不是很好。后来浏览器又提供了getBoundClientRect的方法,这个方法会返回当前元素距离视窗的四个...
利用typescript实现原生css变量的主题切换功能类
前言主题的切换研究过好久了,个人认为目前最好的两种实现:原生css变量实现,性能好,但是不太兼容旧设备利用预处理scss这种做一个主题类名,通过最上层类名变化从而改变嵌套的子类名的颜色,兼容性好,但是需要把所有的类都抽出来单独设置。本着简单+性能的目标,我采用了第一种方案,这种方案也是大佬张鑫旭提供了,文章是:《link rel=alternate网站换肤功能最佳实现》有兴趣弄的话可以先看看大佬的文章了解原理。封装主题的链接引入采用如下格式:<!-- theme --> <link href="<?php $this->options->th...
正确使用vue3的ts类型声明
前言使用了ts最头疼的是什么,除了类型声明应该没有第二家了,那么在vue3中如何正确的声明ts类型,代表着我们踏出了认识vue3的第一步,这非常重要,所以为此水个文章,分享给有需要的人。Volar 插件一开始我对于Volar并没有太大的需要,因为一直使用的Vetur,而且这个插件刚出来时并不完善,各种视频up讲的那个一键分屏功能其实也并不好用,虽然是个很有意思的东西,但是没有那种非要使用它的点,所以当时的我怀着这么一个疑问?为什么要用Volar ?现在我就通过两张图告诉你,它有多香!我们在template里面写代码,绑定变量最烦的是什么,就是我们写了个对象,但是忘了它的属性有哪些啊,使用...

映射类型,对象属性批量设置约束
批量设置属性全部只读interface ObjInterface { a: number; b: number; c: number; } //全部设为只读 type readonlyObj = Readonly<ObjInterface>;鼠标移动到readonlyObj可以发现所有的属性全部设置为只读了。type readonlyObj = { readonly a: number; readonly b: number; readonly c: number; }我们按住ctrl+鼠标左键点击Readonly;可以看到...
索引类型,key的约束
再for循环中我们经常遇到类似这种写法const obj = { a: 1, b: 2, c: 3 }; //遍历obj拿到指定key对应的val数组 function getObjVal(obj:any,keys:string[]) { return keys.map(key => obj[key]); } console.log(getObjVal(obj, ["a", "b"])); console.log(getObjVal(obj, ["d", "e"]...
关于ts 属性“xxx”没有初始化表达式,且未在构造函数中明确赋值的解决方案
ts默认要求class中声明的属性必须初始化,所以,如果存在没有被初始化的属性,就会报这个错误。如果我们让他或者等于null,那么在调用属性的时候又会提示值可能为null,极度麻烦class A { data: { name: string } | null = null; } const a = new A(); console.log(a.data.name);然后你又不得不搞个非空断言。console.log((a.data!).name);每次都这么写非常麻烦。赋值方案既然他要赋值那么我们就赋值class A { data: { name: string }; c...
