Skip to content
On this page

VueUse useLocalStorage & useSessionStorage 源码解析及使用指南

一、核心定位与关系

1. 与 useStorage 的关系

typescript
// 源码实现关系
const useLocalStorage = (key: string, initialValue: any, options?: UseStorageOptions) =>
  useStorage(key, initialValue, localStorage, options)

const useSessionStorage = (key: string, initialValue: any, options?: UseStorageOptions) =>
  useStorage(key, initialValue, sessionStorage, options)

2. 特性对比

特性useLocalStorageuseSessionStorage
数据生命周期永久存储会话级别
作用域同源共享单个标签页
典型应用场景用户偏好设置临时会话状态
存储容量通常 5MB通常 5MB
数据持久性手动清除或过期策略标签页关闭自动清除

二、核心源码解析

1. 函数签名

typescript
// useLocalStorage
function useLocalStorage<T>(
  key: string,
  initialValue: MaybeRef<T>,
  options?: UseStorageOptions<T>
): RemovableRef<T>

// useSessionStorage
function useSessionStorage<T>(
  key: string,
  initialValue: MaybeRef<T>,
  options?: UseStorageOptions<T>
): RemovableRef<T>

2. 源码实现(v9.0.0)

typescript
// 浏览器环境检测
const isClient = typeof window !== 'undefined'

// useLocalStorage 实现
export function useLocalStorage<T extends string | number | boolean | object | null>(
  key: string,
  initialValue: T,
  options: UseStorageOptions<T> = {}
) {
  return useStorage(key, initialValue, isClient ? localStorage : undefined, options)
}

// useSessionStorage 实现
export function useSessionStorage<T extends string | number | boolean | object | null>(
  key: string,
  initialValue: T,
  options: UseStorageOptions<T> = {}
) {
  return useStorage(key, initialValue, isClient ? sessionStorage : undefined, options)
}

三、关键技术实现

1. 存储类型自动切换

typescript
// 服务端渲染处理
const storage = isClient ? targetStorage : undefined

// 隐私模式降级处理
try {
  storage!.setItem(testKey, 'test')
  storage!.removeItem(testKey)
} catch (e) {
  fallbackToMemoryStorage()
}

2. 类型约束增强

typescript
// 参数类型校验
T extends(string|number|boolean|object|null)

3. 存储事件响应

typescript
// 跨窗口同步实现
window.addEventListener('storage', event => {
  if (event.key === key && event.storageArea === storage) {
    updateState(event)
  }
})

四、使用示例大全

1. 基础使用

typescript
// 持久化用户主题设置
const theme = useLocalStorage('user-theme', 'light')

// 会话级购物车数据
const cartItems = useSessionStorage('shopping-cart', [])

// 类型安全示例
interface UserSettings {
  darkMode: boolean
  fontSize: number
}
const settings = useLocalStorage<UserSettings>('settings', {
  darkMode: true,
  fontSize: 14,
})

2. 高级配置

typescript
// 自定义序列化(日期处理)
const dateSerializer = {
  read: (v: string) => new Date(parseInt(v)),
  write: (v: Date) => v.getTime().toString(),
}

const lastLogin = useLocalStorage('last-login', new Date(), {
  serializer: dateSerializer,
})

// 写操作节流控制
const analyticsData = useLocalStorage('analytics', [], {
  flush: 'post',
  deep: true,
})

3. 服务端渲染处理

typescript
// Nuxt.js 集成示例
export const usePersistedState = (key: string, init: any) => {
  const cookie = useCookie(key)
  return process.client ? useLocalStorage(key, init) : ref(cookie.value || init)
}

五、实现原理图解

[Vue Component]
  → 调用 useLocalStorage(key)
    → 触发 useStorage 初始化
      → 检测 localStorage 可用性
        → 成功:建立响应式绑定
        → 失败:降级内存存储
      → 注册 storage 事件监听器
  ↔ 数据变更双向同步

六、注意事项与最佳实践

1. 安全实践

typescript
// 敏感信息加密存储
const encryptSerializer = {
  read: (v: string) => decrypt(v),
  write: (v: any) => encrypt(JSON.stringify(v)),
}

const token = useLocalStorage('auth-token', null, {
  serializer: encryptSerializer,
})

2. 性能优化

typescript
// 大数据分块存储
const LARGE_DATA_KEY = 'large-data'
const chunkSize = 1024 * 1024 // 1MB

const saveLargeData = (data: string) => {
  const chunks = data.match(new RegExp(`.{1,${chunkSize}}`, 'g')) || []
  useLocalStorage(`${LARGE_DATA_KEY}-chunks`, chunks.length)
  chunks.forEach((chunk, i) => {
    useLocalStorage(`${LARGE_DATA_KEY}-${i}`, chunk)
  })
}

3. 错误处理

typescript
// 存储失败降级示例
const persistentState = useLocalStorage(
  'important-data',
  {},
  {
    onError: e => {
      console.error('存储失败,降级内存存储:', e)
      // 显示用户提示
      showToast('本地存储不可用,部分功能受限')
    },
  }
)

七、特殊场景处理

1. 隐私模式兼容

typescript
// 隐私模式检测
const checkStorageAvailable = () => {
  try {
    const testKey = '__storage_test__'
    localStorage.setItem(testKey, testKey)
    localStorage.removeItem(testKey)
    return true
  } catch (e) {
    return false
  }
}

const safeLocalStorage = checkStorageAvailable()
  ? useLocalStorage
  : (key: string, init: any) => ref(init)

2. 跨标签页通信

typescript
// 实现标签页间消息广播
const useTabBroadcast = (channel: string) => {
  const message = useLocalStorage(channel, null)
  const postMessage = (data: any) => (message.value = data)
  const clearMessage = () => (message.value = null)
  return { message, postMessage, clearMessage }
}

八、对比分析

与原生 API 对比

功能原生实现VueUse 实现
响应式更新手动监听 storage 事件自动同步
类型转换需手动 JSON 处理自动序列化
深层次监听不支持支持 deep 配置
错误处理需手动 try/catch内置降级策略
服务端渲染无法直接使用安全降级处理

九、扩展应用

1. 实现过期机制

typescript
const useExpirableStorage = (key: string, ttl: number) => {
  const data = useLocalStorage<{ value: any; expires: number }>(key, null)

  const set = (value: any) => {
    data.value = {
      value,
      expires: Date.now() + ttl,
    }
  }

  const get = () => {
    if (!data.value) return null
    if (Date.now() > data.value.expires) {
      data.value = null
      return null
    }
    return data.value.value
  }

  return { get, set }
}

2. 存储空间监控

typescript
const useStorageQuota = () => {
  const calculateUsage = (storage: Storage) => {
    let total = 0
    for (let i = 0; i < storage.length; i++) {
      const key = storage.key(i)!
      total += (storage.getItem(key)?.length || 0) * 2 // 字节计算
    }
    return total
  }

  return {
    localStorageUsage: () => calculateUsage(localStorage),
    sessionStorageUsage: () => calculateUsage(sessionStorage),
  }
}

十、总结

适用场景建议

  • 🏷️ useLocalStorage 适用

    • 需要长期保存的用户设置
    • 跨会话持久化数据
    • 离线功能数据缓存
  • 🕶️ useSessionStorage 适用

    • 敏感临时数据(如购物车)
    • 单页应用流程状态保持
    • 避免多标签页数据干扰

性能优化要点

  1. 避免存储大型对象(超过 1MB)
  2. 高频更新操作使用 flush: 'post'
  3. 禁用不必要的 deep 监听
  4. 及时清理过期数据

安全建议

  1. 不要存储敏感信息明文
  2. 对用户输入进行严格过滤
  3. 使用 HTTPS 防止中间人攻击
  4. 定期清理第三方库的存储数据

通过合理使用这两个 API,可以在保证数据持久化的同时,保持应用状态的响应式同步,极大提升开发效率和用户体验。

上次更新于: