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 它可以获取父组件传递过来的所有自定义函数,如下: // 父组件 <template><div class"a"><Child abab"handleAbab" acac"handleAcac"/></div> </template><script> impor…...
架构设计笔记-20-补充知识
知识产权 我国没有专门针对知识产权制定统一的法律(知识产权法),而是在民法通则规定的原则下,根据知识产权的不同类型制定了不同的单项法律及法规,如著作权法、商标法、专利法、计算机软件保护条例等,这些法律、法规共同构成了我…...

scrapy 爬虫学习之【中医药材】爬虫
本项目纯学习使用。 1 scrapy 代码 爬取逻辑非常简单,根据url来处理翻页,然后获取到详情页面的链接,再去爬取详情页面的内容即可,最终数据落地到excel中。 经测试,总计获取 11299条中医药材数据。 import pandas as…...
PDH稳频技术粗谈
PDH(Plesiochronous Digital Hierarchy)是一种传输技术,主要用于数字通信中的传输系统。PDH稳频技术是指在PDH传输系统中,通过稳定频率来实现传输系统的稳定性和可靠性。 PDH传输系统中,时钟同步是非常重要的。传输系…...

[LeetCode] 130. 被围绕的区域
题目描述: 给你一个 m x n 的矩阵 board ,由若干字符 X 和 O 组成,捕获 所有 被围绕的区域: 连接:一个单元格与水平或垂直方向上相邻的单元格连接。区域:连接所有 O 的单元格来形成一个区域。围绕&#x…...
C语言位运算
目录 1.C语言位运算符表 2.C语言移位运算符详解(配实例作业) 3.C语言&按位与运算符详解 4.C语言|按位或运算符详解 5.C语言^按位异或运算符详解 6.C语言~取反运算符详解 C语言位运算这一章主要介绍C语言位运算符表、C语言移位运算符、C语言&按…...
Go 语言中格式化动词
当然,我很乐意为你提供 Go 语言中所有的格式化动词的完整列表。Go 语言的格式化动词非常丰富,可以满足各种打印和格式化需求。以下是完整的列表: 通用: %v - 以默认格式打印值 %v - 类似 %v,但对结构体会添加字段名 %#…...

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

大模型涌现判定
什么是大模型? 大模型:是“规模足够大,训练足够充分,出现了涌现”的深度学习系统; 大模型技术的革命性:延申了人的器官的功能,带来了生产效率量级提升,展现了AGI的可行路径&#x…...
LeetCode 1456.定长子串中元音的最大数目
题目: 给你字符串 s 和整数 k 。 请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。 英文中的 元音字母 为(a, e, i, o, u)。 思路:定长滑动窗口 入 更新 出 代码: class Solution {pub…...
freeswitch-esl 三方设备实现监听功能
使用场景: A和B在通话中,C想监听A和B通话内容 方法一: 修改拨号计划<extension name="global" continue="true"><condition><action application="info"/>...

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

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日,Douglas Jia 发布在AMD ROCm 博客上的文章。 在这篇文章中,我们回顾了使用 JAX 对基于双向编码器表示(BERT)的大型语言模型(LL…...

【简单版】通过 Window.performance 实现前端页面(性能)监控
1 背景 前端监控系统告警xx接口fetchError 问题:前端监控系统没有更多的错误信息,查询该fetch请求对应的接口日志返回200状态码、无请求异常记录,且后台能查到通过该fetch请求成功发送的数据。那是前端页面的错误还是前端监控系统的问题&…...

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

手机摄影入门
感觉会摄影的人是能够从生活中发现美的人。 我不太会拍照,觉得拍好的照片比较浪费时间,而且缺乏审美也缺乏技巧,所以拍照的时候总是拍不好。但有时候还是需要拍一些好看的照片的。 心态和审美可能需要比较长时间提升,但一些基础…...
微信小程序手机号授权获取(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读写端口驱动的示例,驱动驱动程序使用一个基于asyn实现了asynCommon和asynOctet的驱动程序-CSDN博客中编写的驱动程序,本程序的C代码如下: #include <stdlib.h> #include <stdio.h> #include <string.h>#…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...