当前位置: 首页 > news >正文

Vue3 让localstorage变响应式

Hook使用方式:

import {useLocalStore} from "../js/hooks"const aa=useLocalStore("aa",1)


需求一:

通过window.localStorage.setItem可以更改本地存储是,还可以更新aa的值

window.localStorage.setItem("aa",100)


需求二:

通过aa.value++;既可以更改js的数据修改试图,还有更新本地存储

需求三:

支持数组,对象,和普通类型数据


实现思路

对于需求一,原生的window.localStorage.setItem肯定无法实现数据响应式所以需要从写改函数

对于需求二,需用用到watch来监听数据的变化
对于上面2个需求的代码实现都封装在useLocalStore函数内部,在内部定义一个响应式的ref数据,然后返回改声明的数据,如下:

import { ref } from 'vue';export const useLocalStore=(key,defaultValue)=>{
const refVal=ref(null);
//省略部分代码….
return ref Val;
}

重写元素localStorage的代码如下:


const nativeLocalStorage = window.localStorage;
window.nativeLocalStorage = nativeLocalStorage; // 保留原生的使用
/*** 没有keyStr时候所有都清空* @param {*} keyStr */class MyLocalStorage {setItem(key, value) {console.log("set key", key, "value", value)nativeLocalStorage.getItem(key, value);if (storeItemSubscribers[key]) {storeItemSubscribers[key].forEach((dep) => {dep.value = value;});}}getItem(key) {//getItem不需要做响应式nativeLocalStorage.getItem(key);}removeItem(key) {if (storeItemSubscribers[key]) {storeItemSubscribers[key].forEach((dep) => {dep.value = null;});}nativeLocalStorage.removeItem(key);}clear() {nativeLocalStorage.clear();for(let key in storeItemSubscribers){if (storeItemSubscribers[key]) {storeItemSubscribers[key].forEach((dep) => {dep.value = null;});}}}
}const myLocalStorage = new MyLocalStorage();
// 将新创建的实例赋值给localStorage
Object.defineProperty(window, 'localStorage', {value: myLocalStorage,writable: true,
});

此外,还需要对默认参数进行判断,区分对象类型和普通类型

在组件销毁前也需要移除依赖收集

整体js

import { onBeforeUnmount, ref, watch } from 'vue';const nativeLocalStorage = window.localStorage;window.nativeLocalStorage = nativeLocalStorage; // 保留原生的使用class MyLocalStorage {setItem(key, value, noUpdate) {console.log("set key", key, "value", value)nativeLocalStorage.getItem(key, value);if (storeItemSubscribers[key]) {storeItemSubscribers[key].forEach((dep) => {dep.value = value;});}}getItem(key) {//getItem不需要做响应式nativeLocalStorage.getItem(key);}removeItem(key) {if (storeItemSubscribers[key]) {storeItemSubscribers[key].forEach((dep) => {dep.value = null;});}nativeLocalStorage.removeItem(key);}clear() {nativeLocalStorage.clear();for(let key in storeItemSubscribers){if (storeItemSubscribers[key]) {storeItemSubscribers[key].forEach((dep) => {dep.value = null;});}}}}const myLocalStorage = new MyLocalStorage();// 将新创建的实例赋值给localStorageObject.defineProperty(window, 'localStorage', {value: myLocalStorage,writable: true,});// LocalStorage项目键与依赖它的Vue实例列表之间的映射const storeItemSubscribers = {};export const useLocalStore = (key, defaultValue) => {const refVal = ref(null);let StringDefaultValue = null;if (typeof defaultValue == "object") {try {StringDefaultValue = JSON.stringify(defaultValue);} catch (e) { }}if (defaultValue != undefined && defaultValue != null) {if (StringDefaultValue) {window.localStorage.setItem(key, StringDefaultValue)}else {window.localStorage.setItem(key, defaultValue)}refVal.value = defaultValue;}const stopWatch = watch(() => refVal.value, () => {let toString = refVal.value;if (typeof defaultValue == "object") {try {toString = JSON.stringify(refVal.value);} catch (e) { }}console.log("触发变化")window.localStorage.setItem(key, toString,true)}, {deep: true,immediate: true})onBeforeUnmount(() => {for (let i = 0; i < storeItemSubscribers[key].length; i++) {if (storeItemSubscribers[key] == refVal) {storeItemSubscribers.splice(i, 1);stopWatch();console.log("组件销毁", i, "storeItemSubscribers.length", storeItemSubscribers.length)break;}}})// 收集依赖的Vue实例if (!storeItemSubscribers[key]) storeItemSubscribers[key] = [];storeItemSubscribers[key].push(refVal)return refVal;}

相关文章:

Vue3 让localstorage变响应式

Hook使用方式&#xff1a; import {useLocalStore} from "../js/hooks"const aauseLocalStore("aa",1) 需求一&#xff1a; 通过window.localStorage.setItem可以更改本地存储是&#xff0c;还可以更新aa的值 window.localStorage.setItem("aa&quo…...

【深度学习】InST,Inversion-Based Style Transfer with Diffusion Models,论文,风格迁移,实战

代码&#xff1a;https://github.com/zyxElsa/InST 论文&#xff1a;https://arxiv.org/abs/2211.13203 文章目录 AbstractIntroductionRelated WorkImage style transferText-to-image synthesisInversion of diffusion models MethodOverview ExperimentsComparison with Sty…...

【CSS】3D卡片效果

效果 index.html <!DOCTYPE html> <html><head><title> Document </title><link type"text/css" rel"styleSheet" href"index.css" /></head><body><div class"card"><img…...

OrderApplication

目录 1 OrderApplication 2 /// 查询订单 2.1.1 //补充商品单位 2.1.2 //补充门店名称 2.1.3 //补充门店名称 2.1.4 //订单售后 2.1.5 //订单项售后 OrderApplication...

如何在保健品行业运用IPD?

保健品是指能调节机体功能&#xff0c;不以治疗为目的&#xff0c;并且对人体不产生任何急性、亚急性或者慢性危害的产品。保健品是食品的一个种类&#xff0c;具有一般食品的共性&#xff0c;其含有一定量的功效成分&#xff0c;能调节人体的机能&#xff0c;具有特定的功效&a…...

Flink系列之:动态发现新增分区

Flink系列之&#xff1a;动态发现新增分区 一、动态发现新增分区二、Flink SQL动态发现新增分区三、Flink API动态发现新增分区 为了在不重新启动 Flink 作业的情况下处理主题扩展或主题创建等场景&#xff0c;可以将 Kafka 源配置为在提供的主题分区订阅模式下定期发现新分区。…...

eclipse版本与jdk版本对应关系

官网&#xff1a;Eclipse/Installation - Eclipsepedia eclipse历史版本&#xff08;2007-&#xff09;&#xff1a;Older Versions Of Eclipse - Eclipsepedia Eclipse Packaging Project (EPP) Releases | Eclipse Packages...

File类的学习

java.io.File类 文件和目录路径的抽象表达形式是一个与操作系统无关的类&#xff0c;任何一个操作系统都可以使用这个类中的方法 File.pathSeparator 文件路径分隔符&#xff0c;windows是分号&#xff0c;linux是&#xff1a; File.separator 文件名分隔符&#xff0c;window…...

Linux 操作系统 Red Hat Enterprise Linux 安装教程

文章目录 笔者的操作环境&#xff1a; 制作环境&#xff1a; Win32 Disk Imager 1.0.0 Windows 10 教育版 ISO&#xff1a; Red Hat Enterprise Linux 9.2 x86_64 Red Hat Enterprise Linux&#xff08;RHEL&#xff09;是一种 Linux 操作系统。安装此操作系统的难题在于&a…...

关于拓扑排序

又重新学了一下拓扑排序&#xff0c;这次发现就十分简单了&#xff0c;拓扑排序的步骤 1.他必须是一个有向无环图&#xff0c;起点我们就是入度为0的点 2.我们首先要输出的就是入度为0的点&#xff0c;然后依次删除这些点连向的点&#xff0c;使这些点的入度-1&#xff0c;如果…...

【C++】开源:Boost库常用组件配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Boost库常用组件配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c…...

用python通过http实现文件传输,分为发送端和接收端

要使用Python通过HTTP实现文件传输&#xff0c;可以使用Python的 requests 库来发送和接收HTTP请求。以下是一个示例代码&#xff0c;其中包括发送端和接收端的实现。 发送端&#xff1a; import requestsdef send_file(file_path, url):with open(file_path, rb) as file:re…...

数据结构--图的遍历 DFS

数据结构–图的遍历 DFS 树的深度优先遍历 //树的先根遍历 void PreOrder(TreeNode *R) {if(R ! NULL){visit(R); //访问根节点while(R还有下一个子树T)PreOrder(T);//先根遍历下一棵子树} }图的深度优先遍历 bool visited [MAX_VERTEX_NUM]; //访问标记数组 void DFS(Grap…...

SpringBoot集成MyBatisPlus+MySQL(超详细)

前言 查看此文章前强烈建议先看这篇文章&#xff1a;Java江湖路 | 专栏目录 该文章纪录的是SpringBoot快速集成MyBatis Plus&#xff0c;每一步都有记录&#xff0c;争取每一位看该文章的小伙伴都能操作成功。达到自己想要的效果~ 文章目录 前言1、什么是MyBatisPlus2、Spring…...

一边是计算机就业哀鸿遍野,一边是高考生疯狂涌向计算机专业

在张雪峰推荐的几大专业里&#xff0c;计算机专业是其中之一。近几年&#xff0c;计算机专业报考热度不减&#xff0c;但就业前景却令人堪忧&#xff0c;互联网裁员接二连三&#xff0c;许多码农找不到工作。 一位网友感叹&#xff1a;一边是计算机就业哀鸿遍野&#xff0c;一…...

解决外部主机无法访问Docker容器的方法

使用Docker启动了一个tomcat容器&#xff0c;并做了端口映射&#xff0c;但是外部主机仍然无法访问。 编辑centos上的配置文件 vi /etc/sysctl.conf net.ipv4.ip_forward1 systemctl restart network保存以后即可生效&#xff0c;这个配置是开启linux的ip数据包转发功能&#…...

IDEA中修改类头的文档注释信息

IDEA中修改类头的文档注释信息 选择File--Settings--Editor--File and Code Templates--Includes&#xff0c;可以把文档注释写成这种的 /**author: Arbicoralcreate: ${YEAR}-${MONTH}-${DAY} ${TIME}Description: */这样回看就可以很清楚的看到自己创建脚本的时间&#xff…...

建模教程:如何利用3ds Max 和 After Effects 实现多通道渲染和后期合成

推荐&#xff1a; NSDT场景编辑器 助你快速搭建可二次开发的3D应用场景 1. 创建基本场景 步骤 1 打开 3ds Max。 打开 3ds Max。 步骤 2 我做了一个简单的场景。我放了三个 彼此之间有一定距离的物体。 制作对象 步骤 3 按 Ctrl-C 键 在透视视图中创建摄影机。 创建相机 …...

JPA之Hibernate

JPA 定义&#xff1a;是 JavaEE 中一组用于持久化数据的 API&#xff0c;它提供了一种标准的 ORM 规范&#xff0c;用于 Java 对象映射到数据库中。 JPA 的开发是为了简化企业级应用程序的开发&#xff0c;降低应用程序与数据库之间的耦合度&#xff0c;并提高应用程序的可维护…...

leetcode(力扣)剑指 Offer 16. 数值的整数次方 (快速幂)

文章目录 题目描述思路分析完整代码 题目描述 实现 pow(x, n) &#xff0c;即计算 x 的 n 次幂函数&#xff08;即&#xff0c;xn&#xff09;。不得使用库函数&#xff0c;同时不需要考虑大数问题。 示例 1&#xff1a; 输入&#xff1a;x 2.00000, n 10 输出&#xff1a;10…...

PostgreSQL CASE语句深度解析:性能、类型与NULL安全实战指南

1. 为什么你必须真正吃透 PostgreSQL 的 CASE 语句——它远不止是 SQL 里的“if-else”翻译器在 PostgreSQL 实战中&#xff0c;我见过太多人把CASE当成一个语法糖&#xff1a;写几个WHEN...THEN&#xff0c;加个ELSE&#xff0c;再套个END&#xff0c;就以为搞定了。结果呢&am…...

从入门到上岗,Java+AI 复合型人才养成攻略

当下编程行业格局正在悄然改变,纯 Java 后端岗位内卷日趋严重,薪资增长逐步放缓;纯粹的 AI 算法岗门槛居高不下,对学历、数理功底要求严苛,普通开发者很难入局。 而Java+AI 复合型开发顺势成为行业刚需岗位,既依托成熟的 Java 体系承接业务开发,又能融入人工智能技术实…...

用数字逻辑门复刻柏林钟:从二进制编码到硬件实现

1. 项目概述&#xff1a;用数字电路复刻“柏林钟”作为一个在柏林长大的孩子&#xff0c;我从小就对库达姆大街上的那座“柏林钟”着迷。它不像传统时钟那样用指针或数字告诉你时间&#xff0c;而是通过几排不同颜色的发光方块&#xff0c;以一种近乎艺术的方式呈现时间。这种独…...

Windows10下V-REP教育版安装保姆级教程(附百度网盘资源与避坑点)

Windows10系统V-REP教育版完整安装指南&#xff1a;从下载到实战避坑在机器人仿真和自动化控制领域&#xff0c;V-REP&#xff08;现更名为CoppeliaSim&#xff09;作为一款功能强大的跨平台机器人仿真软件&#xff0c;已经成为众多工科学生和研究人员的首选工具。特别是其教育…...

37家金融客户紧急启用的DeepSeek扫描辅助加固包(含未公开API调用密钥策略)

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;DeepSeek漏洞扫描辅助的背景与战略价值 近年来&#xff0c;大模型在安全领域的应用正从辅助问答向深度协同防御演进。DeepSeek系列模型凭借其开源、高推理精度及强代码理解能力&#xff0c;成为构建智能化漏洞…...

差分隐私GDP机制紧密度量化:从隐私剖面到∆度量的实践指南

1. 差分隐私GDP机制&#xff1a;从理论到实践&#xff0c;如何量化隐私保护紧密度在差分隐私&#xff08;Differential Privacy, DP&#xff09;的实际部署中&#xff0c;尤其是在机器学习的隐私保护训练&#xff08;如DP-SGD&#xff09;场景里&#xff0c;我们常常面临一个核…...

探索Windows 10上的Android世界:揭秘WSA-Windows-10项目的3个技术突破

探索Windows 10上的Android世界&#xff1a;揭秘WSA-Windows-10项目的3个技术突破 【免费下载链接】WSA-Windows-10 This is a backport of Windows Subsystem for Android to Windows 10. 项目地址: https://gitcode.com/gh_mirrors/ws/WSA-Windows-10 想象一下&#…...

TorchDynamo与TorchInductor:PyTorch编译器生态的完整解析

TorchDynamo与TorchInductor&#xff1a;PyTorch编译器生态的完整解析 【免费下载链接】torchdynamo A Python-level JIT compiler designed to make unmodified PyTorch programs faster. 项目地址: https://gitcode.com/gh_mirrors/to/torchdynamo TorchDynamo 是一个…...

OpenRASP原理与实战:Java应用层实时防护技术详解

1. 为什么我宁愿花三天部署OpenRASP&#xff0c;也不愿再写第五个自定义WAF过滤器去年冬天&#xff0c;我在给一家做在线教育SaaS平台做安全加固时&#xff0c;连续踩了三个坑&#xff1a;第一次用NginxLua写了套SQL注入规则&#xff0c;结果学生提交的“SELECT * FROM courses…...

从模糊到电影级景深:Midjourney + Topaz Gigapixel联调方案(含LUT预设包+PSD分层模板)

更多请点击&#xff1a; https://codechina.net 第一章&#xff1a;从模糊到电影级景深&#xff1a;Midjourney Topaz Gigapixel联调方案&#xff08;含LUT预设包PSD分层模板&#xff09; 当Midjourney生成的图像存在主体边缘柔化、背景层次缺失或分辨率不足等问题时&#xf…...