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

10_实现readonly

在某些时候,我们希望定义一些数据是只读的,不允许被修改,从而实现对数据的保护,即为 readonly

只读本质上也是对数据对象的代理,我们同样可以基于之前实现的 createReactiveObject 函数来实现,可以为此函数添加第三个参数 isReadonly,如下:

function createReactiveObject(value, isShallow = false, isReadonly = false){}

而有了这个参数之后,我们还需要对拦截器进行其他操作,修改或者删除一个对象的属性,都是改变此对象,因此我们需要针对这两个进行拦截,如下:

const noWarnKey = [RAW_KEY, IS_REACTIVE, ITERATE_KEY]// set
function baseSet(isReadonly) {return function set(target, key, newVal, receiver) {// isReadonly 为 true 时,禁止修改,而一些内部属性则忽略if (isReadonly && !noWarnKey.includes(key)) {// 并弹出警告console.warn('只读属性 ', key, ' 禁止修改')return true}const oldVal = target[key]const type = Object.prototype.hasOwnProperty.call(target, key) ? TrggerType.SET : TrggerType.ADDconst result = Reflect.set(target, key, newVal, receiver)if (!result) returnif (receiver[RAW_KEY] === target) {if (!Object.is(oldVal, newVal)) {trigger(target, key, type)}}return result}
}// delete
function baseDeleteProperty(isReadonly) {return function deleteProperty(target, key) {if (isReadonly && !noWarnKey.includes(key)) {console.warn('只读属性 ', key, ' 禁止删除')return true}const hadKey = Object.prototype.hasOwnProperty.call(target, key)const result = Reflect.deleteProperty(target, key)if (hadKey && result) {trigger(target, key, TrggerType.DELETE)}return result}
}// get
function baseGet(isShallow, isReadonly) {return function get(target, key, receiver) {if (key === RAW_KEY) {return target}// 只有当前的对象是一个非只读数据时,才需要收集依赖if (!isReadonly) {track(target, key)}const result = Reflect.get(target, key, receiver)if (isShallow) return resultif (typeof result === 'object' && result !== null) {return reactive(result)}return result}
}function createReactiveObject(value, isShallow = false) {if (typeof value !== 'object' || value === null) {console.warn('value 必须是一个对象')return value}if (reactiveMap.has(value)) {return reactiveMap.get(value)}if (isReactive(value)) return valueconst proxy = new Proxy(value, {get: baseGet(isShallow),set: baseSet(isReadonly),has,ownKeys,deleteProperty: baseDeleteProperty(isReadonly)})proxy[IS_REACTIVE] = truereactiveMap.set(value, proxy)return proxy
}function readonly(value) {return createReactiveObject(value, false, true)
}

现在我们写一段代码进行一下测试:

const obj = { a: 1 }
const r1 = readonly(obj)
r1.a++console.log(r1)

结果如图:

在这里插入图片描述

不过目前还存在一个问题,目前的只读只能处理成浅响应,案例如下:

const obj = {a: 1,b: {c: 3}
}
const r1 = readonly(obj)
r1.b.c++console.log(r1)

测试结果如图:

在这里插入图片描述

我们虽然在创建 readonly 函数时,给 createReactiveObject 的第二个参数是 false,表示是深响应的,但从结果可以看到,没有被拦截,而且依然被修改了。

所以按照之前的经验,如果要深处理,就直接进行递归处理即可,所以我们可以进行如下修改:

function baseGet(isShallow, isReadonly) {return function get(target, key, receiver) {if (key === RAW_KEY) {return target}// 只有当前的对象是一个非只读数据时,才需要收集依赖if (!isReadonly) {track(target, key)}const result = Reflect.get(target, key, receiver)if (isShallow) return result// 在此处进行递归处理if (typeof result === 'object' && result !== null) {// 若开启了只读,则使用 readonly 函数包装结果,实现递归处理每一层return isReadonly ? readonly(result) : reactive(result)}return result}
}

我们在使用之前的测试案例,执行 r1.b.c++ ,来查看一下结果,如图:

在这里插入图片描述

而如果要实现浅响应,那就更加简单了,如下:

function shallowReadonly(value) {// 只需要将 isShallow 设置为 true 即可,表示只处理第一层// - 设置 isShallow 为 true 后,在 get 中,就会直接返回这个属性的原有的值,不做代理、只读或者其他处理return createReactiveObject(value, true, true)
}

相关文章:

10_实现readonly

在某些时候,我们希望定义一些数据是只读的,不允许被修改,从而实现对数据的保护,即为 readonly 只读本质上也是对数据对象的代理,我们同样可以基于之前实现的 createReactiveObject 函数来实现,可以为此函数…...

简单介绍$listeners

$listeners 它可以获取父组件传递过来的所有自定义函数&#xff0c;如下&#xff1a; // 父组件 <template><div class"a"><Child abab"handleAbab" acac"handleAcac"/></div> </template><script> impor…...

架构设计笔记-20-补充知识

知识产权 我国没有专门针对知识产权制定统一的法律(知识产权法)&#xff0c;而是在民法通则规定的原则下&#xff0c;根据知识产权的不同类型制定了不同的单项法律及法规&#xff0c;如著作权法、商标法、专利法、计算机软件保护条例等&#xff0c;这些法律、法规共同构成了我…...

scrapy 爬虫学习之【中医药材】爬虫

本项目纯学习使用。 1 scrapy 代码 爬取逻辑非常简单&#xff0c;根据url来处理翻页&#xff0c;然后获取到详情页面的链接&#xff0c;再去爬取详情页面的内容即可&#xff0c;最终数据落地到excel中。 经测试&#xff0c;总计获取 11299条中医药材数据。 import pandas as…...

PDH稳频技术粗谈

PDH&#xff08;Plesiochronous Digital Hierarchy&#xff09;是一种传输技术&#xff0c;主要用于数字通信中的传输系统。PDH稳频技术是指在PDH传输系统中&#xff0c;通过稳定频率来实现传输系统的稳定性和可靠性。 PDH传输系统中&#xff0c;时钟同步是非常重要的。传输系…...

[LeetCode] 130. 被围绕的区域

题目描述&#xff1a; 给你一个 m x n 的矩阵 board &#xff0c;由若干字符 X 和 O 组成&#xff0c;捕获 所有 被围绕的区域&#xff1a; 连接&#xff1a;一个单元格与水平或垂直方向上相邻的单元格连接。区域&#xff1a;连接所有 O 的单元格来形成一个区域。围绕&#x…...

C语言位运算

目录 1.C语言位运算符表 2.C语言移位运算符详解&#xff08;配实例作业&#xff09; 3.C语言&按位与运算符详解 4.C语言|按位或运算符详解 5.C语言^按位异或运算符详解 6.C语言~取反运算符详解 C语言位运算这一章主要介绍C语言位运算符表、C语言移位运算符、C语言&按…...

Go 语言中格式化动词

当然&#xff0c;我很乐意为你提供 Go 语言中所有的格式化动词的完整列表。Go 语言的格式化动词非常丰富&#xff0c;可以满足各种打印和格式化需求。以下是完整的列表&#xff1a; 通用&#xff1a; %v - 以默认格式打印值 %v - 类似 %v&#xff0c;但对结构体会添加字段名 %#…...

CSS3 动画相关属性实例大全(四)(font、height、left、letter-spacing、line-height 属性)

CSS3 动画相关属性实例大全&#xff08;四) &#xff08;font、height、left、letter-spacing、line-height 属性&#xff09; 本文目录&#xff1a; 一、font 属性&#xff08;所有字体属性&#xff09; 1.1、font-size属性&#xff08;指定字体的大小&#xff09; 1.2、f…...

大模型涌现判定

什么是大模型&#xff1f; 大模型&#xff1a;是“规模足够大&#xff0c;训练足够充分&#xff0c;出现了涌现”的深度学习系统&#xff1b; 大模型技术的革命性&#xff1a;延申了人的器官的功能&#xff0c;带来了生产效率量级提升&#xff0c;展现了AGI的可行路径&#x…...

LeetCode 1456.定长子串中元音的最大数目

题目&#xff1a; 给你字符串 s 和整数 k 。 请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为&#xff08;a, e, i, o, u&#xff09;。 思路&#xff1a;定长滑动窗口 入 更新 出 代码&#xff1a; class Solution {pub…...

freeswitch-esl 三方设备实现监听功能

使用场景: A和B在通话中,C想监听A和B通话内容 方法一: 修改拨号计划<extension name="global" continue="true"><condition><action application="info"/>...

【LeetCode】123.买卖股票的最佳时间

清晰明了的思路是解决问题的至上法宝。如何把一个复杂的问题拆成简单的问题&#xff0c;就是我们需要考虑的。 1. 题目 2. 思想 这道题虽然是难题&#xff0c;但是思想比较简单。 题目要求说至多买卖两次&#xff0c;也就是说&#xff0c;也可以买卖一次&#xff0c;这种情况…...

elk部署安装

elk部署 前提准备1、elasticsearch2、kibana3、logstash 前提准备 1、提前装好docker docker-compose相关命令 2、替换docker仓库地址国内镜像源 cd /etc/docker vi daemon.json # 替换内容 {"registry-mirrors": [ "https://docker.1panel.dev", "ht…...

使用 JAX 进行 LLM 分布式监督微调

LLM distributed supervised fine-tuning with JAX — ROCm Blogs (amd.com) 24年1月25日&#xff0c;Douglas Jia 发布在AMD ROCm 博客上的文章。 在这篇文章中&#xff0c;我们回顾了使用 JAX 对基于双向编码器表示&#xff08;BERT&#xff09;的大型语言模型&#xff08;LL…...

【简单版】通过 Window.performance 实现前端页面(性能)监控

1 背景 前端监控系统告警xx接口fetchError 问题&#xff1a;前端监控系统没有更多的错误信息&#xff0c;查询该fetch请求对应的接口日志返回200状态码、无请求异常记录&#xff0c;且后台能查到通过该fetch请求成功发送的数据。那是前端页面的错误还是前端监控系统的问题&…...

微信小程序考试系统(lw+演示+源码+运行)

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了微信小程序考试系统的开发全过程。通过分析微信小程序考试系统管理的不足&#xff0c;创建了一个计算机管理微信小程序考试系统的方案。文章介绍了微信小程序考…...

手机摄影入门

感觉会摄影的人是能够从生活中发现美的人。 我不太会拍照&#xff0c;觉得拍好的照片比较浪费时间&#xff0c;而且缺乏审美也缺乏技巧&#xff0c;所以拍照的时候总是拍不好。但有时候还是需要拍一些好看的照片的。 心态和审美可能需要比较长时间提升&#xff0c;但一些基础…...

微信小程序手机号授权获取(aes加密手机号)

<view class="container"> <view class=topTabSwiper> <view class=tab {{currentData == 0 ? "tabBorer" : ""}} data-current = "0" bindtap=checkCurrent>一键授权<span class="tab_bor"><…...

asyn queueRequest使用实例

使用queueRequest读写端口驱动的示例&#xff0c;驱动驱动程序使用一个基于asyn实现了asynCommon和asynOctet的驱动程序-CSDN博客中编写的驱动程序&#xff0c;本程序的C代码如下&#xff1a; #include <stdlib.h> #include <stdio.h> #include <string.h>#…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

Ubuntu Cursor升级成v1.0

0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开&#xff0c;快捷键也不好用&#xff0c;当看到 Cursor 升级后&#xff0c;还是蛮高兴的 1. 下载 Cursor 下载地址&#xff1a;https://www.cursor.com/cn/downloads 点击下载 Linux (x64) &#xff0c;…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

flow_controllers

关键点&#xff1a; 流控制器类型&#xff1a; 同步&#xff08;Sync&#xff09;&#xff1a;发布操作会阻塞&#xff0c;直到数据被确认发送。异步&#xff08;Async&#xff09;&#xff1a;发布操作非阻塞&#xff0c;数据发送由后台线程处理。纯同步&#xff08;PureSync…...