likes
comments
collection
share

实战指南:封装localStorge

作者站长头像
站长
· 阅读数 3

我们封装的localStorage.ts文件

我们在src/utils目录中创建localStorage.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的基本操作。

键值检查

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

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

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

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

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格式,则直接返回。

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方法提供了移除某个特定的存储项操作。

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

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

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

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

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

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

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

设置本地存储

测试使用 set 方法:

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中可以看到相应的键值对。

实战指南:封装localStorge

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

读取本地存储

测试使用 get 方法:

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

实战指南:封装localStorge

删除和清空本地存储

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

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中被删除全部清空

实战指南:封装localStorge