1. 为什么需要浏览器存储?

在前端开发中,数据的持久化存储是刚需场景。用户的主题偏好、表单草稿、购物车信息等数据都需要在页面刷新甚至关闭后依然存在。传统方案需要手动操作localStorage/sessionStorage的API,而VueUse提供响应式的解决方案,让我们看看如何用更优雅的方式实现需求。

2. 环境搭建与基础配置

使用Vite创建Vue3项目:

npm create vite@latest my-vueus-ssr -- --template vue-ts

安装核心依赖:

npm install @vueuse/core

在组件中按需引入:

import { useLocalStorage, useSessionStorage } from '@vueuse/core'

3. useLocalStorage实战教学

3.1 主题切换记忆功能

<script setup lang="ts">
import { useLocalStorage } from '@vueuse/core'

// 类型安全的主题配置
type Theme = 'light' | 'dark' | 'system'

// 响应式主题状态,自动同步到localStorage
const theme = useLocalStorage<Theme>('theme-preference', 'system')

// 切换主题方法
const toggleTheme = () => {
  theme.value = theme.value === 'dark' ? 'light' : 'dark'
  document.documentElement.classList.toggle('dark')
}
</script>

<template>
  <button @click="toggleTheme">
    当前主题:{{ theme }}(点击切换)
  </button>
</template>

功能亮点:

  • 类型校验保障值安全
  • 状态变更自动写入存储
  • 支持复杂类型序列化

3.2 表单草稿自动保存

<script setup lang="ts">
import { useLocalStorage } from '@vueuse/core'

// 定义复杂的表单数据类型
interface DraftForm {
  title: string
  content: string
  attachments: string[]
  lastSaved?: Date
}

// 初始化带时间戳的表单草稿
const formDraft = useLocalStorage<DraftForm>('editor-draft', {
  title: '',
  content: '',
  attachments: [],
  lastSaved: new Date()
})

// 自动保存逻辑(示例使用防抖)
const autoSave = useDebounceFn(() => {
  formDraft.value.lastSaved = new Date()
}, 1000)
</script>

<template>
  <input v-model="formDraft.title" @input="autoSave" />
  <textarea v-model="formDraft.content" @input="autoSave" />
  <p>最后保存时间:{{ formDraft.lastSaved?.toLocaleString() }}</p>
</template>

4. useSessionStorage应用解析

4.1 购物车临时存储

<script setup lang="ts">
import { useSessionStorage } from '@vueuse/core'

type CartItem = {
  id: string
  name: string
  price: number
  quantity: number
}

// 初始化购物车数据结构
const shoppingCart = useSessionStorage<CartItem[]>('session-cart', [])

// 添加商品方法
const addToCart = (item: Omit<CartItem, 'quantity'>) => {
  const existItem = shoppingCart.value.find(i => i.id === item.id)
  existItem ? existItem.quantity++ : shoppingCart.value.push({ ...item, quantity: 1 })
}
</script>

安全特性:

  • 标签页隔离保障数据独立
  • 关闭浏览器自动清除数据
  • 同源跨页面同步机制

4.2 多步骤表单状态保持

<script setup lang="ts">
import { useSessionStorage } from '@vueuse/core'

// 定义多步骤表单结构
interface MultiStepFormState {
  currentStep: number
  personalInfo: {
    name: string
    email: string
  }
  paymentInfo: {
    cardNumber: string
    expiry: string
  }
}

// 初始化会话存储
const formState = useSessionStorage<MultiStepFormState>('multi-step-form', {
  currentStep: 1,
  personalInfo: { name: '', email: '' },
  paymentInfo: { cardNumber: '', expiry: '' }
})

// 导航方法
const goToStep = (step: number) => {
  formState.value.currentStep = Math.max(1, Math.min(step, 3))
}
</script>

5. 存储方案对比指南

特性 localStorage sessionStorage
生命周期 永久存储 会话级存储
作用域 同源跨标签页 单个标签页
容量限制 通常5MB 通常5MB
数据共享 所有同源窗口 仅当前窗口
适用场景 长期偏好设置 临时会话数据

6. 技术实现深度剖析

6.1 核心优势

  • 响应式同步:数据变更自动更新DOM与存储
  • 类型安全:完善的TypeScript支持
  • 序列化智能处理:自动处理JSON转换
  • 存储事件监听:支持跨窗口更新同步

6.2 潜在局限

  • SSR限制:需配合useSSR插件使用
  • 大文件存储:超过5MB会抛出错误
  • 敏感数据风险:需自行加密处理
  • 同步延迟:批量操作可能产生性能问题

7. 专家级实践建议

  1. 数据加密:敏感信息必须加密存储
import CryptoJS from 'crypto-js'

const encryptedStorage = useLocalStorage('secret', {
  get: () => decrypt(localStorage.getItem('key')),
  set: (value) => localStorage.setItem('key', encrypt(value))
})
  1. 容量监控:添加存储溢出处理
try {
  useLocalStorage('big-data', hugeArray)
} catch (error) {
  console.error('存储失败:', error)
  showUserNotification('存储空间不足')
}
  1. 数据迁移:版本控制方案
const STORAGE_VERSION = '2.0'
const legacyData = localStorage.getItem('old-key')
if (legacyData) {
  useLocalStorage('new-key').value = migrateData(legacyData)
}

8. 应用场景全景展望

  • 用户偏好:主题、语言、字体大小
  • 数据缓存:接口返回的频繁读取数据
  • 工作恢复:文档编辑器自动保存
  • 状态持久化:SPA应用的页面状态保持
  • 离线功能:配合Service Worker实现

9. 总结与展望

VueUse的存储方案极大提升了开发效率,但需注意数据安全性问题。未来可探索:

  • 与IndexedDB结合处理大文件
  • 服务端渲染的深度适配
  • 存储压缩算法的集成优化