localStorage
关于 cookie、sessionStorage、localStorage 三者的区别主要如下:
存储大小: cookie 数据大小不能超过 4k,sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到 5M 或更大
有效时间:localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据; sessionStorage 数据在当前浏览器窗口关闭后自动删除;cookie 设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭
数据与服务器之间的交互方式, cookie 的数据会自动的传递到服务器,服务器端也可以写 cookie 到客户端; sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存
特点
- 生命周期:持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的
- 存储的信息在同一域中是共享的
- 当本页操作(新增、修改、删除)了 localStorage 的时候,本页面不会触发 storage 事件,但是别的页面会触发 storage 事件。
- 大小:5M(跟浏览器厂商有关系)
- localStorage 本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
- 受同源策略的限制
localStorage 也不是完美的,它有两个缺点:
无法像 Cookie 一样设置过期时间 只能存入字符串,无法直接存对象
js
localStorage.setItem('key', { name: 'value' })
console.log(localStorage.getItem('key')) // '[object, Object]'使用
js
// 设置
localStorage.setItem('username', 'cfangxu')
// 获取
localStorage.getItem('username')
// 获取键名
localStorage.key(0) // 获取第一个键名
// 删除
localStorage.removeItem('username')
// 一次性清除所有存储
localStorage.clear()缓存
ts
import { version } from '../package.json'
type Awaitable<T> = T | Promise<T>
type StorageValue = string | Record<string, unknown>
export interface Storage {
getItem: (key: string) => Awaitable<any | null>
setItem: <T extends StorageValue = StorageValue>(key: string, value: T) => Awaitable<void>
}
export function memoryStorage() {
const cache = new Map<string, unknown>()
return {
getItem(key: string) {
return cache.get(key)
},
setItem(key: string, value: StorageValue) {
cache.set(key, value)
},
} satisfies Storage
}
const ONE_WEEK = 1000 * 60 * 60 * 24 * 7
export function createAsyncStorage(storage: Storage) {
return {
async getItem<T = unknown>(key: string, init?: () => T | Promise<T>) {
const now = Date.now()
const res = await storage.getItem(key)
if (res && res.expires > now && res.version === version) {
return res.data
}
if (!init) {
return null
}
const data = await init()
await storage.setItem(key, { expires: now + ONE_WEEK, version, data })
return data
},
async setItem(key: string, data: unknown) {
await storage.setItem(key, { expires: Date.now() + ONE_WEEK, version, data })
},
}
}ts
const googleFonts = await ctx.storage.getItem('google:meta.json', () => $fetch<{ familyMetadataList: FontIndexMeta[] }>('https://fonts.google.com/metadata/fonts', { responseType: 'json' }).then(r => r.familyMetadataList))