纯手工模拟Vue中的数据劫持和代理

news2024/12/26 22:46:29

为什么要实现数据劫持和代理

举一个场景:比如在小程序开发中,我们需要逻辑层修改的数据能同步响应更新到视图层的页面上,那么底层框架在实现这种效果的时候,机制是什么样的呢?
其实这里的底层原理类似于Vue中的数据劫持和代理。所以,弄懂前端中的数据劫持和代理是非常重要的,对我们理解如何实现响应式具有非常重要的意义,本文主要通过一个小小的样例,来展示如何通过最简单直接的代码来实现(如有不对,欢迎大家批评指正,希望和大家一起学习,一起进步)。

如何实现数据劫持和代理

我们所要实现的核心功能就是:一个模拟的_this对象,能够动态的将data数据进行劫持和代理,并且能够通过_this对象进行获取和修改,通过修改之后的数据在data和_this对象中都能够同步更新。

1)模拟数据

// 模拟数据
let data = {
	userName: "harry",
	age: 20
}

2)模拟对象

// 模拟组件的实例
let _this = {

}

3)通过Object.defineProperty() 函数进行数据的劫持和代理
3.1 方法介绍
Object.defineProperty()

/**
	 * Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
	 * 
	 * 语法:Object.defineProperty(obj, prop, descriptor)
	 * 
	 * 参数:
	 * obj 要定义属性的对象
	 * prop 要定义或者修改的属性的名称
	 * descriptor 要定义或者修改的属性描述符
	 * 
	 * 返回值:
	 * 被传递非函数的对象(obj)
	 * 
	 **/

3.2 get方法介绍
get() 方法用来获取拓展属性值,当获取该属性值的时候调用get方法;
比如:

for(let item in data){
	Object.defineProperty(_this, item, {
		get(){
			console.log("get()");
			return data[item];
		}
	});
}

console.log(_this)

在这里插入图片描述
当点击age和userName的时候,就会自动调用get()方法:
在这里插入图片描述
在这里插入图片描述

3.3 set方法介绍
set 监视拓展属性的,只要一修改对象的值就会自动调用,具体将在3.4中介绍。

3.4 错误的直接修改方法
比如在for循环之外,使用直接修改的方法,来看看是否生效。
原本的数据:
在这里插入图片描述
修改方法:
在这里插入图片描述
结果:
在这里插入图片描述
没有变化。表明没有修改成功,所以通过这种方法是不能直接作用于get方法添加的拓展属性。但是,这里要注意,虽然没有修改成功,但还是会调用set方法。
验证一下是否调用set方法;

set(newValue){
			console.log('set()', newValue)
			// 同时注意: 如果在这里使用_this.userName = newValue 会出现死循环,因为会再次调用set方法
		}

每次直接修改的时候,都会出现newValue(新的值)。
在这里插入图片描述
那么会有同学想到在_this的set方法中直接通过_this.userName = newValue 来进行过值得修改,是否可行呢?
听起来是可行的,但是我们分析一下:因为我们如果通过这种方式进行值得修改得时候,会调用set方法,而set方法中又有修改值得操作,所有又会调用set方法。。。这样就会导致深度无限递归操作,所以是不行的。

3.5 正确的修改方法
那么正确的修改方法是什么呢?
我们可以通过迂回战术,先去修改data,然后通过_this获取数据的时候,就会通过get方法进行响应式获取新值,从而达到数据同步更新的结果。
具体代码实现则为:


// 模拟数据
let data = {
	userName: "harry",
	age: 20
}


// 模拟组件的实例
let _this = {

}

// 利用Object.defineProperty() 进行数据的劫持代理
for(let item in data){
	// console.log(item, data[item]);

	/**
	 * Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
	 * 
	 * 语法:Object.defineProperty(obj, prop, descriptor)
	 * 
	 * 参数:
	 * obj 要定义属性的对象
	 * prop 要定义或者修改的属性的名称
	 * descriptor 要定义或者修改的属性描述符
	 * 
	 * 返回值:
	 * 被传递非函数的对象(obj)
	 * 
	 **/
	Object.defineProperty(_this, item, {
		// get 用来获取拓展属性值的,当获取该属性值的时候调用get方法
		get(){
			console.log("get()");
			return data[item];
		},

		// set 监视拓展属性的,只要一修改就调用
		set(newValue){
			console.log('set()', newValue)
			// *** 换个思路,先修改data数据,这样的话,下一次_this对象获取的值就会是修改之后的值
			data[item] = newValue;

			// 同时注意: 如果在这里使用_this.userName = newValue 会出现死循环,因为会再次调用set方法
		}
	});
}

console.log(_this)
// 通过Object.defineProperty() 的get方法添加的拓展属性不能直接作用于对象的属性修改
_this.userName = 'wade'	//因为这里进行了数据的修改,所以会调用set函数

console.log(_this.userName)	//但通过_this.userName = 'wade' 来进行直接修改是不生效的

最重要的就是set方法中的data[item] = newValue 这一句。

总结

这里通过Object.defineProperty() 函数实现了数据的劫持和代理,通过这种方式,实现了框架的响应式,不过只是最简单版本的,可以帮助理解。加油。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/173377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于蜣螂算法优化的BP神经网络(预测应用) - 附代码

基于蜣螂算法优化的BP神经网络(预测应用) - 附代码 文章目录基于蜣螂算法优化的BP神经网络(预测应用) - 附代码1.数据介绍3.蜣螂优化BP神经网络3.1 BP神经网络参数设置3.2 蜣螂算法应用4.测试结果:5.Matlab代码摘要&am…

ClickHouse快速复习

ClickHouse​一.特性​1.列式数据库管理系统​2.数据压缩​3.数据的磁盘存储​4.支持SQL​5.索引​6.适合在线查询​7.支持数据复制和数据完整性​8.实时的数据更新​9.处理大量短查询的吞吐量​10.处理大量短查询的吞吐量​11.限制​二.数据类型​1.数字类型​2.浮点数(float)…

前端都在聊什么 - 第 1 期

Hello 小伙伴们早上、中午、下午、晚上、深夜好,我是爱折腾的 jsliang~「前端都在聊什么」是 jsliang 日常写文章/做视频/搞直播过程中,小伙伴们的提问以及我的解疑整理。本期对应 2023 年的 01.01-01.15 这个时间段。本期针对「工作」「学习」「规划」「…

迭代器、可迭代对象、生成器的区别和联系

目录1 迭代器2 可迭代对象3 生成器1 迭代器 迭代器是一种可以更新迭代的工具,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。但是他不能像列表一样使用下标来获取数据,也就是说迭代器是不能返回的。迭代器只能往前不会…

Universal Links方式:私有化部署服务器来托管apple-app-site-association文件创建通用链接

Universal Links方式:私有化部署服务器来托管apple-app-site-association第一步:开启Associated Domains服务第二步:配置Associated Domains(域名)第三步:服务器配置apple-app-site-association文件第四步:…

java的数据类型:引用数据类型(String、数组、枚举)

2.3.3 引用数据类型 引用数据类型大致包括:类、 接口、 数组、 枚举、 注解、 字符串等 它和基本数据类型的最大区别就是: 基本数据类型是直接保存在栈中的引用数据类型在栈中保存的是一个地址引用,这个地址指向的是其在堆内存中的实际位置…

四旋翼无人机学习第22节--padstack editor创建过孔

1 首先打开padstack editor软件。 2、选择过孔,注意与前面的博客不同,这里的单位最好使用mil。 在小马哥的教程中,过孔可以分为几类,下面主要对下图的五种过孔进行设置。 3、接着对过孔的孔径进行设置。 4、不做修改。 5、修…

网络交换机常见故障及解决方法

在日常的网络故障维护中我们接触最多的设备就是交换机,特别是接入层交换机,它是连接用户和交换路由设备的桥梁。但是交换机设备无论性能多么好,都会存在潜在故障问题,就像人一样,无论多么健康,也总会出现一…

MindMaster思维导图及亿图图示会员 优惠活动

MindMaster思维导图及亿图图示会员 超值获取途径 会员九折优惠方法分享给大家!如果有需要,可以上~ 以下是食用方法: MindMaster 截图 亿图图示 截图 如果需要MindMaster思维导图或者亿图图示会员,可按照如下操作领取超值折扣优惠…

java成员变量/局部变量2023017

成员变量/局部变量 1.定义位置不同,成员变量定义在类里,局部变量定义在类的方法里。 来自网络 2.成员变量中,其中类变量从该类的准备阶段起开始存在,直到系统完全销毁这个类,类变量的作用域与这个类的生存范围相同&…

超市进销存之openGauss数据库的应用与实践

目录 一、背景 二、目的 三、什么是“进销存”,什么是超市进销存管理系统? 四、什么是openGauss数据库? 五、应用与实践(模拟超市进销存系统) 1、超市进销存数据库表设计 2、创建数据库表 3、手工插入数据 4、…

Python:使用xlrd过滤execl表中数据

一、写代码前需要注意事项首先我们需要注意:python xlrd库的新版本2.0.1版本移除了对.xlsx格式的支持,只支持.xls格式。报错信息如下:File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xlrd/__ini…

react17+ts 学习

文章目录前言一、创建一个react项目启动项目项目打包打包命令npm run eject的作用入口文件分析react的设计理念二、创建一个reacttypescript的项目创建项目命令如何让react支持json引入不报错react为什么使用jsxjsx特点jsx命令规范jsx表示对象如何在jsx中防止注入攻击&#xff…

Spring的三种装配机制(XML、JavaConfig、自动配置)

Spring中bean有三种装配机制 一、在xml中显示装配 1. 基本类型装配 Data NoArgsConstructor AllArgsConstructor public class Student{private String name;private Address address;private String[] books;private List<String> hobbys;private Map<String Stri…

Linux常见命令 14 - 软/硬连接命令 ln

目录 1. 软连接 ln -s 2. 硬连接 ln 目前Linux中比较常用的是软连接&#xff0c;硬连接不常用&#xff0c;掌握基本的软连接常识即可 1. 软连接 ln -s 语法&#xff1a;ln -s [源文件] [目标文件] liuSLR:/hd1/Dling/lane/Wmq/test$ ln -s hello.txt hello.txt.soft liuS…

28. 实战:基于selenium实现12306自动购票

目录 前言 目的 思路 代码实现 1. 进入登录界面&#xff0c;输入账号密码 2. 点击登录按钮&#xff0c;完成滑块验证 3. 在个人中心点击购票&#xff0c;跳转 4. 输入出发地、目的地&#xff0c;从控制台输入得到 5. 文本框输入出发日 6. 若是学生票则切换票型 7. 点…

离线增量文章画像计算

2.5 离线增量文章画像计算 学习目标 目标 了解增量更新代码过程应用 无 2.5.1 离线文章画像更新需求 文章画像&#xff0c;就是给每篇文章定义一些词。 关键词&#xff1a;TEXTRANK IDF共同的词 主题词&#xff1a;TEXTRANK ITFDF共同的词 更新文章时间&#xff1a; 1、…

10.1002.1:VectorDraw Web /VectorDraw Developer Crack

VectorDraw 网络库 VectorDraw Web Library 是一个矢量图形库&#xff0c;旨在不仅可以打开 CAD 绘图&#xff0c;还可以在任何支持 HTML 5 标准的平台&#xff08;例如 Windows、Android、IOS 和 Linux&#xff09;上显示通用矢量对象。它可以在支持使用 canvas 和 Javascript…

DW动手学数据分析Task3:数据重构)

目录1 数据的合并1.1合并方法一&#xff1a;用concat函数1.2 合并方法二&#xff1a;使用DataFrame自带的方法join方法和append1.3 合并方法三&#xff1a;使用Panads的merge方法和DataFrame的append方法2 换一种角度看数据3 数据聚合与运算3.1 groupby机制3.2 数据运算1 数据的…

论文浅尝 | 利用常识知识图增强零样本和少样本立场检测

笔记整理&#xff1a;张嘉芮&#xff0c;天津大学硕士链接&#xff1a;https://aclanthology.org/2021.findings-acl.278.pd动机传统的数据驱动方法不适用于零样本和少样本的场景。对于人类来说&#xff0c;常识知识是理解和推理的关键因素。在没有标注数据和用户立场的隐晦表达…