Vue3 的 useLocalStorage 📦

基础封装

  1. 初始化数据,如果 localStorage 中已有对应的数据则使用 localStorage 的值
  2. 使用 onMounted 来确保组件已经挂载后再执行操作
  3. data 添加一个监听器
  4. 监听 data 的变化,并将新值保存到 localStorage
js 复制代码
import { ref, onMounted, watchEffect } from 'vue';

function useLocalStorage(key, defaultValue) {
  const data = ref(localStorage.getItem(key) || defaultValue);

  onMounted(() => {
    const localStorageUpdate = () => {
      localStorage.setItem(key, data.value);
    };

    watchEffect(localStorageUpdate);
  });

  return data;
}

export default useLocalStorage;

使用

每当输入框的值发生变化时,它会自动更新localStorage,并且如果你刷新页面,它会保留之前的值。

js 复制代码
<template>
  <el-input v-model="text" />
  {{ text }}
</template>

<script lang="ts" setup>
import { ref } from "vue";
import useLocalStorage from "../hooks/useLocalStorage.js";

const text = useLocalStorage("myText", "Default Text");
</script>

支持更多数据类型

因为localStorage只能存储字符串,当涉及到存储函数(function类型)或其他非字符串/JSON类型数据时,需要特殊处理。在存储和检索函数时,将其序列化为字符串,然后在检索时反序列化。

js 复制代码
import { ref, onMounted, watchEffect } from "vue";

function useLocalStorage(key, defaultValue) {
  const storedValue = localStorage.getItem(key);

  const data = ref(storedValue ? deserialize(storedValue) : defaultValue);

  onMounted(() => {
    const localStorageUpdate = () => {
      localStorage.setItem(key, serialize(data.value));
    };

    watchEffect(localStorageUpdate);
  });

  // 反序列化数据
  function deserialize(value) {
    try {
      const deserialized = JSON.parse(value);
      if (typeof deserialized === "object" && deserialized !== null) {
        return deserialized;
      } else if (typeof deserialized === "function") {
        return new Function(`return ${deserialized}`)();
      } else {
        return deserialized;
      }
    } catch (e) {
      return value;
    }
  }

  // 序列化数据
  function serialize(value) {
    if (typeof value === "function") {
      return value.toString();
    } else if (Array.isArray(value)) {
      return JSON.stringify(value);
    } else if (typeof value === "object" && value !== null) {
      return JSON.stringify(value);
    } else {
      return value;
    }
  }

  return data;
}

export default useLocalStorage;

到期删除

在现有的自定义useLocalStorage hook 中增加一个配置项,以控制数据的有效期。

onMounted,向 localStorage 中设置时间戳

js 复制代码
localStorage.setItem(`${key}_timestamp`, Date.now().toString());

使用 setInterval,在组件的生命周期内定期检查数据是否过期,然后在过期时手动删除它。

js 复制代码
onMounted(() => {
  localStorage.setItem(`${key}_timestamp`, Date.now().toString());

  //....

  const checkExpiration = () => {
    if (
      expiration &&
      storedTimestamp &&
      Date.now() - parseInt(storedTimestamp) > expiration
    ) {
      localStorage.removeItem(key);
      localStorage.removeItem(`${key}_timestamp`);
    }
  };

  setInterval(checkExpiration, 1000);
});

完整代码:

js 复制代码
import { ref, onMounted, watchEffect } from "vue";

function useLocalStorage(key, defaultValue, expiration) {
  const storedValue = localStorage.getItem(key);
  const storedTimestamp = localStorage.getItem(`${key}_timestamp`);

  const data = ref(storedValue ? deserialize(storedValue) : defaultValue);

  onMounted(() => {
    localStorage.setItem(`${key}_timestamp`, Date.now().toString());

    const localStorageUpdate = () => {
      localStorage.setItem(key, serialize(data.value));
    };

    watchEffect(localStorageUpdate);

    const checkExpiration = () => {
      if (
        expiration &&
        storedTimestamp &&
        Date.now() - parseInt(storedTimestamp) > expiration
      ) {
        localStorage.removeItem(key);
        localStorage.removeItem(`${key}_timestamp`);
      }
    };

    setInterval(checkExpiration, 1000);
  });

  // 反序列化数据
  function deserialize(value) {
    try {
      const deserialized = JSON.parse(value);
      if (typeof deserialized === "object" && deserialized !== null) {
        return deserialized;
      } else if (typeof deserialized === "function") {
        return new Function(`return ${deserialized}`)();
      } else {
        return deserialized;
      }
    } catch (e) {
      return value;
    }
  }

  // 序列化数据
  function serialize(value) {
    if (typeof value === "function") {
      return value.toString();
    } else if (
      Array.isArray(value) ||
      (typeof value === "object" && value !== null)
    ) {
      return JSON.stringify(value);
    } else {
      return value;
    }
  }

  return data;
}

export default useLocalStorage;
相关推荐
香蕉可乐荷包蛋3 小时前
浅入ES5、ES6(ES2015)、ES2023(ES14)版本对比,及使用建议---ES6就够用(个人觉得)
前端·javascript·es6
未来之窗软件服务4 小时前
资源管理器必要性———仙盟创梦IDE
前端·javascript·ide·仙盟创梦ide
西哥写代码5 小时前
基于cornerstone3D的dicom影像浏览器 第十八章 自定义序列自动播放条
前端·javascript·vue
清风细雨_林木木5 小时前
Vue 中生成源码映射文件,配置 map
前端·javascript·vue.js
雪芽蓝域zzs6 小时前
JavaScript splice() 方法
开发语言·javascript·ecmascript
森叶7 小时前
Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
前端·javascript·electron
霸王蟹7 小时前
React 19 中的useRef得到了进一步加强。
前端·javascript·笔记·学习·react.js·ts
霸王蟹7 小时前
React 19版本refs也支持清理函数了。
前端·javascript·笔记·react.js·前端框架·ts
繁依Fanyi7 小时前
ColorAid —— 一个面向设计师的色盲模拟工具开发记
开发语言·前端·vue.js·编辑器·codebuddy首席试玩官
codelxy7 小时前
vue引用cesium,解决“Not allowed to load local resource”报错
javascript·vue.js