实战指南:封装localStorge

本文是《React管理平台》第六节

原生的 localStorage 接口并不支持存储复杂数据类型。为了解决这些问题,本文将介绍高效、安全的封装 localStorage 的方法。

我们封装的localStorage.ts文件

我们在src/utils目录中创建localStorage.ts文件,该文件的代码为:

ts 复制代码
// localStorage.ts
type Storable = string | number | boolean | null | { [key: string]: Storable } | Storable[]

function checkKey(key: string, action: string) {
  if (!key) {
    throw new Error(`${action}操作失败:缺少key`)
  }
}

export default {
  set(key: string, value: Storable) {
    checkKey(key, 'set')

    if (typeof value === 'undefined') {
      throw new Error(`${key}值为undefined`)
    }

    let valueToStore: string

    switch (typeof value) {
      case 'object':
        if (value === null) {
          valueToStore = 'null'
        } else {
          valueToStore = JSON.stringify(value)
        }
        break
      default:
        valueToStore = value.toString()
    }

    localStorage.setItem(key, valueToStore)
  },

  get<T extends Storable = Storable>(key: string): T | undefined {
    checkKey(key, 'get')

    const rawValue = localStorage.getItem(key)

    if (!rawValue) {
      return undefined
    }

    try {
      if (rawValue === 'true') return true as never as T
      if (rawValue === 'false') return false as never as T
      if (rawValue === 'null') return null as never as T
      return JSON.parse(rawValue) as T
    } catch (error) {
      if (error instanceof SyntaxError) {
        return rawValue as never as T
      }
      throw error
    }
  },

  remove(key: string) {
    checkKey(key, 'remove')

    localStorage.removeItem(key)
  },

  clear(): void {
    localStorage.clear()
  },

  getAllKeys(): string[] {
    return Object.keys(localStorage)
  },

  has(key: string) {
    checkKey(key, 'has')

    return localStorage.getItem(key) !== null
  }
}

了解localStorage

我们回顾一下localStorage的基础知识:localStorage是一种Web存储功能,它允许网页在用户浏览器中存储键值对信息。这些数据不会随着浏览器关闭而失效,而是长期存在。

功能封装:优雅的操作接口

封装的目的在于简化操作,提高代码的可读性与可维护性。接下来我们就具体看看如何封装localStorage的基本操作。

键值检查

javascript 复制代码
function checkKey(key: string, action: string) {
  if (!key) {
    throw new Error(`${action}操作失败:缺少key`)
  }
}

在进行任何操作之前,我们通过checkKey方法来确保所需的key值存在。如果key值缺失,会抛出错误。

数据设置:灵活存储多种数据类型

set方法允许存储字符串、数字、布尔值、null,甚至是对象或数组(作为JSON字符串存储)。在存储前会对值进行检查和转换,保证数据准确存入localStorage。

javascript 复制代码
set(key: string, value: Storable) {
  if (typeof value === 'undefined') {
      throw new Error(`${key}值为undefined`)
    }

    let valueToStore: string

    switch (typeof value) {
      case 'object':
        if (value === null) {
          valueToStore = 'null'
        } else {
          valueToStore = JSON.stringify(value)
        }
        break
      default:
        valueToStore = value.toString()
    }
    // ...
}

数据获取

get方法通过解析返回原始的数据类型。如果数据并非true、false、null或JSON格式,则直接返回。

javascript 复制代码
get<T extends Storable = Storable>(key: string): T | undefined {
  // 省略的参数检查代码
  try {
      if (rawValue === 'true') return true as never as T
      if (rawValue === 'false') return false as never as T
      if (rawValue === 'null') return null as never as T
      return JSON.parse(rawValue) as T
    } catch (error) {
      if (error instanceof SyntaxError) {
        return rawValue as never as T
      }
      throw error
    }
}

数据移除:简单删除指定键值

remove方法提供了移除某个特定的存储项操作。

javascript 复制代码
remove(key: string) {
  // 省略的参数检查代码
  localStorage.removeItem(key)
}

清空数据:一键清除所有存储

clear方法用于清除localStorage中的所有数据,为应用提供了快速的数据重置方式。

其他辅助方法:提高查询效率

我们还提供了getAllKeyshas方法,分别用于获取所有存储的键和检查特

使用自定义的localStorage工具进行数据管理

接下来我们测试封装的localStorage方法

设置本地存储

测试使用 set 方法:

tsx 复制代码
import storage from '@/utils/localStorage.ts'

export const Welcome = () => {
  function handleSetLocalStorage() {
    storage.set('string', '辰火流光')

    storage.set('number', 666)

    storage.set('json', { name: '辰火流光', age: 30 })

    storage.set('numberArray', [1, 2, 3])

    storage.set('stringArray', ['a', 'b', 'c'])

    storage.set('array', [
      { name: '辰火流光', age: 30 },
      { name: '辰火流光', age: 30 },
      { name: '辰火流光', age: 30 }
    ])

    storage.set('null', null)

    // storage.set('error', undefined)


    storage.set('boolean', true)
  }

  return (
    <div>
      <button onClick={handleSetLocalStorage}>setLocalStorage</button>
    </div>
  )
}

成功执行上述代码后,在浏览器的localStorage中可以看到相应的键值对。

代码storage.set('error', undefined)会报错:Uncaught Error: error值为undefined 因为我们限制了值不能为undefined,而错误中提示的error其实是调用该方法的key名称

读取本地存储

测试使用 get 方法:

tsx 复制代码
import storage from '@/utils/localStorage.ts'

export const Welcome = () => {
  function handleGetLocalStorage() {
    console.log(storage.get('string'))
    console.log(typeof storage.get('string'))

    console.log(storage.get('number'))
    console.log(typeof storage.get('number'))

    console.log(storage.get('json'))
    console.log(typeof storage.get('json'))

    console.log(storage.get('numberArray'))
    console.log(typeof storage.get('numberArray'))

    console.log(storage.get('stringArray'))
    console.log(typeof storage.get('stringArray'))

    console.log(storage.get('array'))
    console.log(typeof storage.get('array'))

    console.log(storage.get('null'))
    console.log(typeof storage.get('null'))

    console.log(storage.get('boolean'))
    console.log(typeof storage.get('boolean'))

    console.log(storage.get('不存在的key'))
    console.log(typeof storage.get('不存在的key'))
  }

  return (
    <div>
      <button onClick={handleGetLocalStorage}>getLocalStorage</button>
    </div>
  )
}

在浏览器控制台,我们看到从storage.get返回的值及其对应的数据类型。如果查询一个不存在的键,则返回undefined

删除和清空本地存储

我们也来看看如何删除特定键 和如何清除整个localStorage

tsx 复制代码
import storage from '@/utils/localStorage.ts'

export const Welcome = () => {
  function handleRemoveClick() {
    storage.remove('string')
  }

  function handleClearClick() {
    storage.clear()
  }

  return (
    <div>
      <button onClick={handleRemoveClick}>remove</button>
      <button onClick={handleClearClick}>clear</button>
    </div>
  )
}

执行上述代码后,会看到对应的键值对从浏览器的localStorage中被删除全部清空

相关推荐
前端拾光者27 分钟前
利用D3.js实现数据可视化的简单示例
开发语言·javascript·信息可视化
Json_181790144801 小时前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库
风尚云网1 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
木子02041 小时前
前端VUE项目启动方式
前端·javascript·vue.js
GISer_Jing1 小时前
React核心功能详解(一)
前端·react.js·前端框架
捂月1 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
深度混淆1 小时前
实用功能,觊觎(Edge)浏览器的内置截(长)图功能
前端·edge
Smartdaili China1 小时前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理
秦老师Q1 小时前
「Chromeg谷歌浏览器/Edge浏览器」篡改猴Tempermongkey插件的安装与使用
前端·chrome·edge
滴水可藏海1 小时前
Chrome离线安装包下载
前端·chrome