本文是《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中的所有数据,为应用提供了快速的数据重置方式。
其他辅助方法:提高查询效率
我们还提供了getAllKeys
和has
方法,分别用于获取所有存储的键和检查特
使用自定义的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中被删除 与全部清空。