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使用方式: import {useLocalStore} from "../js/hooks"const aauseLocalStore("aa",1) 需求一: 通过window.localStorage.setItem可以更改本地存储是,还可以更新aa的值 window.localStorage.setItem("aa&quo…...

【深度学习】InST,Inversion-Based Style Transfer with Diffusion Models,论文,风格迁移,实战
代码:https://github.com/zyxElsa/InST 论文: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?
保健品是指能调节机体功能,不以治疗为目的,并且对人体不产生任何急性、亚急性或者慢性危害的产品。保健品是食品的一个种类,具有一般食品的共性,其含有一定量的功效成分,能调节人体的机能,具有特定的功效&a…...
Flink系列之:动态发现新增分区
Flink系列之:动态发现新增分区 一、动态发现新增分区二、Flink SQL动态发现新增分区三、Flink API动态发现新增分区 为了在不重新启动 Flink 作业的情况下处理主题扩展或主题创建等场景,可以将 Kafka 源配置为在提供的主题分区订阅模式下定期发现新分区。…...

eclipse版本与jdk版本对应关系
官网:Eclipse/Installation - Eclipsepedia eclipse历史版本(2007-):Older Versions Of Eclipse - Eclipsepedia Eclipse Packaging Project (EPP) Releases | Eclipse Packages...
File类的学习
java.io.File类 文件和目录路径的抽象表达形式是一个与操作系统无关的类,任何一个操作系统都可以使用这个类中的方法 File.pathSeparator 文件路径分隔符,windows是分号,linux是: File.separator 文件名分隔符,window…...

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

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

【C++】开源:Boost库常用组件配置使用
😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍Boost库常用组件配置使用。 无专精则不能成,无涉猎则不能通。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,…...
用python通过http实现文件传输,分为发送端和接收端
要使用Python通过HTTP实现文件传输,可以使用Python的 requests 库来发送和接收HTTP请求。以下是一个示例代码,其中包括发送端和接收端的实现。 发送端: 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(超详细)
前言 查看此文章前强烈建议先看这篇文章:Java江湖路 | 专栏目录 该文章纪录的是SpringBoot快速集成MyBatis Plus,每一步都有记录,争取每一位看该文章的小伙伴都能操作成功。达到自己想要的效果~ 文章目录 前言1、什么是MyBatisPlus2、Spring…...

一边是计算机就业哀鸿遍野,一边是高考生疯狂涌向计算机专业
在张雪峰推荐的几大专业里,计算机专业是其中之一。近几年,计算机专业报考热度不减,但就业前景却令人堪忧,互联网裁员接二连三,许多码农找不到工作。 一位网友感叹:一边是计算机就业哀鸿遍野,一…...
解决外部主机无法访问Docker容器的方法
使用Docker启动了一个tomcat容器,并做了端口映射,但是外部主机仍然无法访问。 编辑centos上的配置文件 vi /etc/sysctl.conf net.ipv4.ip_forward1 systemctl restart network保存以后即可生效,这个配置是开启linux的ip数据包转发功能&#…...

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

建模教程:如何利用3ds Max 和 After Effects 实现多通道渲染和后期合成
推荐: NSDT场景编辑器 助你快速搭建可二次开发的3D应用场景 1. 创建基本场景 步骤 1 打开 3ds Max。 打开 3ds Max。 步骤 2 我做了一个简单的场景。我放了三个 彼此之间有一定距离的物体。 制作对象 步骤 3 按 Ctrl-C 键 在透视视图中创建摄影机。 创建相机 …...
JPA之Hibernate
JPA 定义:是 JavaEE 中一组用于持久化数据的 API,它提供了一种标准的 ORM 规范,用于 Java 对象映射到数据库中。 JPA 的开发是为了简化企业级应用程序的开发,降低应用程序与数据库之间的耦合度,并提高应用程序的可维护…...

leetcode(力扣)剑指 Offer 16. 数值的整数次方 (快速幂)
文章目录 题目描述思路分析完整代码 题目描述 实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。 示例 1: 输入:x 2.00000, n 10 输出:10…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...