localStorage 是浏览器提供的一种持久化存储机制,用于在客户端存储数据。虽然 localStorage 本身已经非常简单易用,但在实际开发中,我们通常会对它进行二次封装,以增强其功能、简化调用、提高代码的可维护性。


1. 为什么要二次封装 localStorage

  1. 简化调用:封装后可以提供更简洁的 API,减少重复代码。
  2. 类型安全localStorage 存储的数据都是字符串,封装后可以自动处理类型转换。
  3. 统一管理:可以统一管理存储的键名,避免键名冲突。
  4. 增强功能:可以扩展功能,例如设置过期时间、数据加密等。

2. 二次封装的核心功能

2.1 数据存储与读取

封装 setItemgetItem 方法,支持存储和读取多种数据类型(如对象、数字等)。

2.2 数据删除

封装 removeItem 方法,支持删除指定键名的数据。

2.3 数据清空

封装 clear 方法,支持清空所有存储的数据。

2.4 数据过期

扩展功能,支持设置数据的过期时间。

2.5 数据加密

扩展功能,支持对存储的数据进行加密。


3. 代码实现

以下是一个完整的 localStorage 二次封装示例:

class Storage {
  /**
   * 存储数据
   * @param {string} key - 存储的键名
   * @param {any} value - 存储的值
   * @param {number} expire - 过期时间(单位:毫秒)
   */
  static setItem(key, value, expire = null) {
    const storageData = {
      value, // 存储的值
      time: Date.now(), // 存储时间
      expire: expire ? Date.now() + expire : null, // 过期时间
    };
    localStorage.setItem(key, JSON.stringify(storageData));
  }

  /**
   * 获取数据
   * @param {string} key - 存储的键名
   * @returns {any} - 存储的值
   */
  static getItem(key) {
    const dataStr = localStorage.getItem(key);
    if (!dataStr) return null;

    const storageData = JSON.parse(dataStr);
    const { value, time, expire } = storageData;

    // 检查数据是否过期
    if (expire && Date.now() > expire) {
      this.removeItem(key); // 删除过期数据
      return null;
    }

    return value;
  }

  /**
   * 删除数据
   * @param {string} key - 存储的键名
   */
  static removeItem(key) {
    localStorage.removeItem(key);
  }

  /**
   * 清空所有数据
   */
  static clear() {
    localStorage.clear();
  }

  /**
   * 加密数据
   * @param {string} data - 需要加密的数据
   * @returns {string} - 加密后的数据
   */
  static encrypt(data) {
    return btoa(encodeURIComponent(data)); // Base64 编码
  }

  /**
   * 解密数据
   * @param {string} data - 需要解密的数据
   * @returns {string} - 解密后的数据
   */
  static decrypt(data) {
    return decodeURIComponent(atob(data)); // Base64 解码
  }
}

4. 功能解析

4.1 数据存储与读取
  • setItem 方法支持存储任意类型的数据(如字符串、数字、对象等),并自动将其转换为 JSON 字符串。
  • getItem 方法支持读取数据,并自动将 JSON 字符串解析为原始数据。
4.2 数据删除
  • removeItem 方法用于删除指定键名的数据。
4.3 数据清空
  • clear 方法用于清空所有存储的数据。
4.4 数据过期
  • setItem 方法中,可以设置数据的过期时间(单位:毫秒)。
  • getItem 方法中,会检查数据是否过期。如果过期,则自动删除数据并返回 null
4.5 数据加密
  • encrypt 方法使用 Base64 编码对数据进行加密。
  • decrypt 方法使用 Base64 解码对数据进行解密。

5. 使用示例

5.1 存储数据
// 存储字符串
Storage.setItem('name', 'John');

// 存储对象
Storage.setItem('user', { name: 'John', age: 30 });

// 存储数据并设置过期时间(1 小时后过期)
Storage.setItem('token', 'abc123', 60 * 60 * 1000);
5.2 读取数据
// 读取字符串
const name = Storage.getItem('name');
console.log(name); // 输出: John

// 读取对象
const user = Storage.getItem('user');
console.log(user); // 输出: { name: 'John', age: 30 }

// 读取过期数据
const token = Storage.getItem('token');
console.log(token); // 如果已过期,输出: null
5.3 删除数据
Storage.removeItem('name');
5.4 清空数据
Storage.clear();
5.5 数据加密
// 加密数据
const encrypted = Storage.encrypt('Hello, World!');
console.log(encrypted); // 输出: SGVsbG8sIFdvcmxkIQ==

// 解密数据
const decrypted = Storage.decrypt(encrypted);
console.log(decrypted); // 输出: Hello, World!

6. 扩展功能

6.1 命名空间

为了避免键名冲突,可以为存储的数据添加命名空间。

class Storage {
  static setItem(key, value, expire = null) {
    const namespace = 'my-app-'; // 命名空间
    const storageData = {
      value,
      time: Date.now(),
      expire: expire ? Date.now() + expire : null,
    };
    localStorage.setItem(namespace + key, JSON.stringify(storageData));
  }

  static getItem(key) {
    const namespace = 'my-app-'; // 命名空间
    const dataStr = localStorage.getItem(namespace + key);
    if (!dataStr) return null;

    const storageData = JSON.parse(dataStr);
    const { value, time, expire } = storageData;

    if (expire && Date.now() > expire) {
      this.removeItem(key);
      return null;
    }

    return value;
  }

  static removeItem(key) {
    const namespace = 'my-app-'; // 命名空间
    localStorage.removeItem(namespace + key);
  }
}
6.2 数据压缩

对于存储大量数据的情况,可以使用压缩算法(如 LZString)对数据进行压缩。

import LZString from 'lz-string';

class Storage {
  static setItem(key, value, expire = null) {
    const storageData = {
      value: LZString.compress(JSON.stringify(value)), // 压缩数据
      time: Date.now(),
      expire: expire ? Date.now() + expire : null,
    };
    localStorage.setItem(key, JSON.stringify(storageData));
  }

  static getItem(key) {
    const dataStr = localStorage.getItem(key);
    if (!dataStr) return null;

    const storageData = JSON.parse(dataStr);
    const { value, time, expire } = storageData;

    if (expire && Date.now() > expire) {
      this.removeItem(key);
      return null;
    }

    return JSON.parse(LZString.decompress(value)); // 解压数据
  }
}

7. 总结

通过对 localStorage 的二次封装,可以实现以下目标:

  1. 简化调用,提供更友好的 API。
  2. 支持多种数据类型的存储和读取。
  3. 支持数据过期、加密、压缩等扩展功能。
  4. 提高代码的可维护性和可扩展性。

更多推荐