Vue3本地存储实现方案

在 Vue 3 中实现本地存储(如用户配置数据),主要通过浏览器提供的 localStoragesessionStorage API。以下是详细实现方案:

基础实现(原生 API)

javascript

复制

下载

复制代码
// 存储数据
localStorage.setItem('userSettings', JSON.stringify({ theme: 'dark', fontSize: 16 }));

// 读取数据
const settings = JSON.parse(localStorage.getItem('userSettings')) || {};

// 删除数据
localStorage.removeItem('userSettings');

推荐方案:封装响应式存储工具

/src/composables/useLocalStorage.js 中创建可复用逻辑:

javascript

复制

下载

复制代码
import { ref, watchEffect } from 'vue';

export default function useLocalStorage(key, defaultValue) {
  // 创建响应式引用
  const storedValue = ref(JSON.parse(localStorage.getItem(key)) || defaultValue);
  
  // 监听变化并存储
  watchEffect(() => {
    localStorage.setItem(key, JSON.stringify(storedValue.value));
  });

  // 提供清除方法
  const clearStorage = () => {
    localStorage.removeItem(key);
    storedValue.value = defaultValue;
  };

  return [storedValue, clearStorage];
}

在组件中使用

vue

复制

下载

复制代码
<script setup>
import { computed } from 'vue';
import useLocalStorage from '@/composables/useLocalStorage';

// 使用存储钩子(带默认值)
const [userSettings, clearSettings] = useLocalStorage('userConfig', {
  theme: 'light',
  fontSize: 14,
  notifications: true
});

// 修改配置
const toggleTheme = () => {
  userSettings.value.theme = userSettings.value.theme === 'light' ? 'dark' : 'light';
};

// 计算属性示例
const themeClass = computed(() => `theme-${userSettings.value.theme}`);
</script>

<template>
  <div :class="themeClass">
    <button @click="toggleTheme">切换主题</button>
    <button @click="clearSettings">重置配置</button>
    
    <input 
      type="range" 
      min="12" max="24"
      v-model.number="userSettings.fontSize"
    >
  </div>
</template>

高级技巧

  1. 存储加密(敏感数据):

    javascript

    复制

    下载

    复制代码
    import CryptoJS from 'crypto-js';
    
    const SECRET_KEY = import.meta.env.VITE_STORAGE_SECRET;
    
    // 加密存储
    const encryptedData = CryptoJS.AES.encrypt(
      JSON.stringify(data),
      SECRET_KEY
    ).toString();
    
    // 解密读取
    const bytes = CryptoJS.AES.decrypt(storedData, SECRET_KEY);
    const originalData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
  2. 类型安全存取

    javascript

    复制

    下载

    复制代码
    // 增强版存储方法
    const typedStorage = {
      get(key, type = 'string') {
        const value = localStorage.getItem(key);
        if (value === null) return null;
        
        try {
          return {
            'number': Number(value),
            'boolean': value === 'true',
            'object': JSON.parse(value),
            'array': JSON.parse(value)
          }[type] || value;
        } catch {
          return value;
        }
      },
      set(key, value) {
        const type = typeof value;
        const toStore = ['object', 'array'].includes(type) 
          ? JSON.stringify(value) 
          : value;
        localStorage.setItem(key, toStore);
      }
    };

注意事项

  1. 存储限制

    • 单个域名存储上限通常为 5MB

    • 单个键值对建议不超过 2MB

  2. 最佳实践

    javascript

    复制

    下载

    复制代码
    // 1. 添加存储版本控制
    const STORAGE_VERSION = 'v1';
    const storageKey = `${STORAGE_VERSION}_userConfig`;
    
    // 2. 添加存储错误处理
    try {
      localStorage.setItem(key, data);
    } catch (e) {
      console.error('存储失败:', e);
      // 降级方案:使用 sessionStorage 或内存存储
    }
    
    // 3. 监听跨标签页更新
    window.addEventListener('storage', (event) => {
      if (event.key === storageKey) {
        // 更新本地数据
        userSettings.value = JSON.parse(event.newValue);
      }
    });
  3. 替代方案选择

    方案 特点 适用场景
    localStorage 永久存储 用户配置、长期数据
    sessionStorage 标签页关闭即清除 临时表单数据
    IndexedDB 大容量存储 (250MB+) 离线应用、大型数据
    Cookies 自动携带到请求头 身份认证

完整示例(TypeScript 版)

typescript

复制

下载

复制代码
// useLocalStorage.ts
import { ref, watch, Ref } from 'vue';

type StorageValue<T> = Ref<T>;

export default function useLocalStorage<T>(
  key: string, 
  defaultValue: T
): [StorageValue<T>, () => void] {
  
  const storedValue = ref(defaultValue) as StorageValue<T>;
  
  // 初始化读取
  try {
    const item = localStorage.getItem(key);
    if (item !== null) {
      storedValue.value = JSON.parse(item);
    }
  } catch (error) {
    console.error(`读取 ${key} 失败:`, error);
  }
  
  // 监听变化
  watch(storedValue, (newVal) => {
    try {
      localStorage.setItem(key, JSON.stringify(newVal));
    } catch (error) {
      console.error(`存储 ${key} 失败:`, error);
    }
  }, { deep: true });
  
  const clear = () => {
    localStorage.removeItem(key);
    storedValue.value = defaultValue;
  };
  
  return [storedValue, clear];
}

通过这种方式,您可以:

  • 创建响应式的持久化存储

  • 自动同步 localStorage 变化

  • 支持复杂对象存储

  • 提供类型安全(TypeScript)

  • 处理存储异常情况

相关推荐
一 乐3 小时前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
BillKu3 小时前
Vue3 + TypeScript + Element Plus 表格行按钮不触发 row-click 事件、不触发勾选行,只执行按钮的 click 事件
vue.js·elementui·typescript
小前端大牛马3 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js
萌萌哒草头将军5 小时前
🚀🚀🚀VSCode 发布 1.101 版本,Copilot 更全能!
前端·vue.js·react.js
摇摇奶昔x7 小时前
Vue.js 中 “require is not defined“
前端·javascript·vue.js
sunbyte8 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | RandomChoicePicker(标签生成)
前端·javascript·vue.js
z_y_j2299704389 小时前
vue前端项目打包和部署
前端·javascript·vue.js
lbchenxy9 小时前
antd vue a-range-picker如何设置不能选择当前和之后的时间,包含时分秒
前端·javascript·vue.js
前端小白从0开始9 小时前
前端基础知识ES6系列 - 01(var、let、const之间的区别)
前端·javascript·vue.js·es6
前端呆猿11 小时前
Vuex:Vue.js 应用程序的状态管理模式
android·vue.js·flutter