Vue3 功能实战 —— 使用 Ts 泛型封装本地存储

9a69fede8b2044a79dd834e3e48f20b4.png前期回顾f8e3cc1a0f694ac2b665ca2ad14c49d7.png   

NVM —— 你把我玩明白_彩色之外的博客-CSDN博客本文将学习 使用 NVM 管理node版本https://blog.csdn.net/m0_57904695/article/details/130670262?spm=1001.2014.3001.5501

目录

 新建  \src\utils\storage-utils.ts

使用

泛型示例

泛型交换变量

泛型 string

泛型 对象

本文完!


👍 本文专栏:开发技巧  

 新建  \src\utils\storage-utils.ts

interface StorageUtilsInterface<T> {
  set(key: string, value: T): void;
  get(key: string): T | null;
  remove(key: string): void;
}

class LocalStorageUtils<T> implements StorageUtilsInterface<T> {
  set(key: string, value: T): void {
    localStorage.setItem(key, JSON.stringify(value));
  }

  get(key: string): T | null {
    const item = localStorage.getItem(key);
    if (item) {
      try {
        return JSON.parse(item);
      } catch (error) {
        console.error("Error parsing stored value:", error);
      }
    }
    return null;
  }

  remove(key: string): void {
    localStorage.removeItem(key);
  }
}

class SessionStorageUtils<T> implements StorageUtilsInterface<T> {
  set(key: string, value: T): void {
    sessionStorage.setItem(key, JSON.stringify(value));
  }

  get(key: string): T | null {
    const item = sessionStorage.getItem(key);
    if (item) {
      try {
        return JSON.parse(item);
      } catch (error) {
        console.error("Error parsing stored value:", error);
      }
    }
    return null;
  }

  remove(key: string): void {
    sessionStorage.removeItem(key);
  }
}

export { LocalStorageUtils, SessionStorageUtils };

使用


onMounted(() => {
  
  const localStorageUtils = new LocalStorageUtils<string>();

  // 设置localStorage
  localStorageUtils.set("username", "张坤");

  // 获取localStorage
  const username = localStorageUtils.get("username");
  console.log("username=====>", username); // "张坤"

  // 删除localStorage
  // setTimeout(() => {
  //   localStorageUtils.remove("username");
  // }, 2000);

  const sessionStorageUtils = new SessionStorageUtils<number>();

  // 设置sessionStorage
  sessionStorageUtils.set("age", 18);

  // 获取sessionStorage
  const age = sessionStorageUtils.get("age");
  console.log("age=====>", age); // 18

  // 删除sessionStorage
  // setTimeout(() => {
  //   sessionStorageUtils.remove("age");
  // }, 4000);
});

泛型示例

首先,什么是泛型?

泛型是一种模板机制,它允许在定义函数、类、接口等时使用类型参数(也称为类型变量),从而实现代码的复用。这里的类型参数可以是任何类型,在使用时可以传入具体的类型。

举个例子,假设我们要写一个函数来交换两个变量的值:

泛型交换变量

function swap(a: { value: any }, b: { value: any }) {
  const temp = a.value;
  a.value = b.value;
  b.value = temp;
}

let x = { value: 1 };
let y = { value: 2 };

swap(x, y);

console.log(x.value, y.value); // 输出 2, 1

上面的代码看起来没什么问题,但是有一个问题是:函数参数的类型都是any,也就是说这个函数可以交换任意类型的值,包括字符串、对象等等,这并不是我们想要的。

这时候,我们可以使用泛型来改进这个函数:

 function swap<T>(tuple: [T, T]): [T, T] {
    return [tuple[1], tuple[0]];
  }
  let tuple: [string, string] = ["张坤", "18"];
  console.log("交换前:", tuple);
  tuple = swap(tuple);
  console.log("交换后:", tuple);

输出:

交换前:Array [ "张坤", "18" ]

交换后:Array [ "18", "张坤" ]

在这个例子中,我们使用了类型参数<T>,并将其应用到函数参数上。这样,我们就可以指定要交换的值的类型。

泛型 string

接下来,再看看泛型接口StorageUtilsInterface<T>

这个接口定义了三个方法——set()get()remove(),它们都使用了类型参数<T>`,表示这些方法可以处理任意类型的值。比如,如果我们用这个接口存储一个字符串类型的值

const storage: StorageUtilsInterface<string> = new LocalStorageUtils();

storage.set('name', 'Tom');

const name = storage.get('name'); // name 的类型为 string | null

这里我们将<T>替换成了string,这样这个接口中的方法就会操作字符串类型的值了。

泛型 对象

如果要存储对象类型的值,可以将StorageUtilsInterface<T>中的类型参数<T>替换为对象类型。比如,假设我们有一个用户对象:

interface User {
  name: string;
  age: number;
}

const user: User = { name: 'Tom', age: 18 };

我们可以使用泛型接口StorageUtilsInterface<T>来存储这个对象:

const storage: StorageUtilsInterface<User> = new LocalStorageUtils();

storage.set('user', user);

const savedUser = storage.get('user'); // savedUser 的类型为 User | null

这里我们将<T>替换成了User,这样这个接口中的方法就会操作User类型的值了。在调用set()方法时,我们需要将user对象传给它,并且在调用get()方法后,返回的值的类型也会变成User | null,表示可能返回一个User类型的值或者null

需要注意的是,在这个例子中,User类型必须是一个可序列化的对象,即该对象可以转换为字符串并通过JSON.parse()方法解析回来。否则,在调用set()方法时会抛出异常。为了确保对象可序列化,我们可以为User类型添加一个[Serializable]标记,或者手动实现toJSON()fromJSON()方法。

本文完!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Vue 3 + TypeScript 中,泛型是一个非常常用的技巧,可以帮助我们编写出更通用、可复用的代码。下面是一个泛型的高级运用实例: 假设我们有一个表单组件,它的数据模型是一个对象,其中每个属性都有一个对应的输入框,我们可以编写一个 `Form` 组件来实现这个表单。为了让 `Form` 组件更通用,我们可以使用泛型来实现: ```typescript // 定义表单数据模型的类型 interface FormModel { [key: string]: any } // 定义表单项的类型 interface FormItem<T> { label: string prop: keyof T } // 定义表单组件的 props 类型 interface FormProps<T extends FormModel> { model: T items: Array<FormItem<T>> } // 定义表单组件 export default defineComponent<FormProps<FormModel>>({ name: 'Form', props: { model: Object as PropType<FormModel>, items: Array as PropType<Array<FormItem<FormModel>>> }, setup(props) { const handleSubmit = () => { // 处理表单提交逻辑 } return { handleSubmit } } }) ``` 在上面的代码中,我们定义了一个 `Form` 组件,它接收两个 props:`model` 和 `items`,其中 `model` 是一个泛型类型,它可以是任意一个类似于表单数据模型的对象,`items` 是一个数组,其中每个元素都是一个 `FormItem` 类型的对象,表示一个表单项。在组件中,我们使用 `keyof` 关键字来获取泛型类型 `T` 的所有属性名,然后使用 `Array<FormItem<T>>` 来表示 `items` 的类型,这样就可以在使用组件时传入任意一个数据模型和表单项,从而实现组件的通用性和灵活性。 以上是一个 Vue 3 + TypeScript 中泛型的高级运用实例,通过使用泛型,我们可以编写出更通用、可复用的组件和方法,从而提高代码的复用性和灵活性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

彩色之外

你的打赏是我创作的氮气加速动力

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

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

打赏作者

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

抵扣说明:

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

余额充值