Vue2响应式原理详解

Object.defineProperty

通过Object.defineProperty方法进行数据代理, 用vm对象的属性来代理data对象的属性

方法案例

 /* 此方法用于定义或修改对象属性的方法。它允许你精确地控制属性的行为,包括属性的值、可枚举性、可配置性和可写性。 接受三个参数:1 要定义属性的对象、2属性名以及一个3描述符对象。描述符对象包含了你想要定义的属性的特性。描述符对象的属性包括:value: 属性的值,默认为 undefined。writable: 属性是否可写,默认为 false。enumerable: 属性是否可枚举,默认为 false。configurable: 属性是否可配置,默认为 false。*/ let person = {} // 定义一个空对象Object.defineProperty(person, 'name', {value: 'ZhangSan',writable: false,enumerable: true,configurable: false,})console.log(person.name);person.name = "Bob" // 这行代码不会修改 'name' 属性的值,因为 'writable' 属性被设置为 falsefor (let key in person) {console.log(key + ': ' + person[key]); // 只会输出 'name: John',因为 'enumerable' 属性被设置为 true}delete person.name; // 这行代码不会删除 'name' 属性,因为 'configurable' 属性默认为 falseconsole.log('name' in person); // 输出 true,'name' 属性仍然存在于对象中

观察者Observer   订阅者Watcher模式

在Observer类中递归遍历data对象,对data对象中的每个属性都进行数据劫持,都指定一个getter、setter。

例外的,对于数组,不能通过object.defineProperty()进行数据代理,因为监听的数组下标变化时会出现数据错乱问题,所以数组是调用数组重写的原生方法来实现响应式。

当通过vm对象修改data对象中的属性时,会触发data属性的setter方法,然后触发它Dep实例的notify方法进行依赖分发,通知所有依赖的Watcher实例执行内部回调函数。

最后会触发renderWatcher回调,会重新执行render函数,重新对比新旧虚拟DOM,重新渲染页面。

模拟Observer类和 watcher 工作原理:

//简单的示例,展示了如何使用观察者模式实现数据劫持:// 观察者类class Observer {constructor(data) {this.data = data;this.observe(data)}// 监听observe(obj) {// 判断是否是一个对象类型if (!obj || typeof obj !== 'object') {return}Object.keys(obj).forEach(key => {// 拿到对象中的每一个属性console.log(obj, key, obj[key], '拿到对象中的每一个属性--------');this.defineReactive(obj, key, obj[key])// 是否有多层嵌套。this.observe(obj[key])})}// 定义对象的响应式属性的方法defineReactive(obj, key, value) {let _this = this;let dep = new Dep();Object.defineProperty(obj, key, {enumerable: true,configurable: true,get() {// 收集依赖if (Dep.target) {dep.addSub(Dep.target);}return value;},set(newValue) {if (newValue === value) {return;}value = newValue;// 通知所有订阅者dep.notify();}});}}// 代表一个依赖(Dependency)管理器  用于管理和通知订阅者class Dep {constructor() {this.subs = [];}// 添加订阅者addSub(sub) {console.log(sub, '添加订阅者-----------');this.subs.push(sub);}// 通知订阅者notify() {this.subs.forEach(sub => {sub.update();});}}// 订阅者class Watcher {constructor(vm, key, changeFunc) {this.vm = vm;this.key = key;this.changeFunc = changeFunc;Dep.target = this;this.vm[this.key]; // 触发 getter,收集依赖 没有此代码 订阅者不会被添加 也不会调用update方法 Dep.target = null;}update() {console.log(this.vm, this.vm[this.key], '更新中---------');// call 是函数对象的一个方法,它允许你调用一个函数并指定函数内部 this 的值,以及传递其他参数。this.changeFunc.call(this.vm, this.vm[this.key]);}}// 用法示例let data = {name: 'Alice',age: 30};// 创建观察者类 观察data中数据发生变化let observer = new Observer(data);// 创建 Watcher 实例 订阅者订阅data中name属性是否发生改变 并且改变的时候执行什么操作let watcher = new Watcher(data, 'name', function (value) {console.log('Name changed:', this, value);});// 修改数据,触发通知console.log(data.name, '更改前----------');data.name = 'Bob'; // 输出: Name changed: Bob

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

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

相关文章

React useEffect Hook: 理解和解决组件双重渲染问题

在React中,useEffect可能会在组件的每次渲染后运行,这取决于它的依赖项。如果你发现useEffect运行了两次,并且你正在使用React 18或更高版本的严格模式(Strict Mode),这可能是因为在开发模式下,…

PyTorch 的 hook 功能监控和分析模型的内部状态

PyTorch 的 hook 功能是一种强大的工具,它允许用户在模型的前向传播(forward pass)和后向传播(backward pass)的任意点插入自定义函数。这些自定义函数可以用于监控、分析、调试或修改模型的内部状态,如激活…

轻松掌握抖音自动点赞技巧,快速吸粉

在当今这个信息爆炸的时代,抖音作为短视频领域的领头羊,不仅汇聚了庞大的用户群体,也成为了品牌和个人展示自我、吸引粉丝的重要平台。如何在众多内容创作者中脱颖而出,实现高效引流获客,精准推广自己的内容&#xff0…

上海、苏大南京师范大学自考新闻作品投稿成功

编辑v:yangwei013049,课程全部考完了,现在头疼两篇公开发表的文章,有谁知道如何可以让稿件能快速发表!因为时间已经不多了,想参加下半年的论文答辩,如果去投稿一是不知道人家用不用你的稿子&…

SHAP,一个解释机器学习模型Python库

SHAP库概述 SHAP(SHapley Additive exPlanations)是一个Python库,用于解释任何机器学习模型的预测.它基于博弈论中的Shapley值概念,可以帮助用户理解模型预测中各个特征的贡献度. 安装与使用 # 命令安装SHAP库:pip install shap使用SHAP库…

工厂策略模式

工厂模式用于干掉大量的if-else ,策略模式用于挪去臃肿的业务代码,还可以进一步升级加上模板模式,以及抽取成Starter public interface HandlerStrategy extends InitializingBean {void findSyncOrders(); }public class SalesPlatformFact…

LVS负载均衡超详细入门介绍

LVS 一、LVS入门介绍 1.1.LVS负载均衡简介 1.2.负载均衡的工作模式 1.2.1.地址转换NAT(Network Address Translation) 1.2.2.IP隧道TUN(IP Tunneling) 1.2.3.直接路由DR(Direct Routing) 1.3.…

桥接模式(合成/聚合复用原则)

桥接模式 文章目录 桥接模式合成/聚合复用原则桥接模式通过示例了解桥接模式 合成/聚合复用原则 合成/聚合复用原则(CARP),尽量使用合成/聚合,尽量不要使用类继承 ​ 合成(Composition),也有翻译成组合)和**聚合(Aggregation)**都是关联的特殊种类。聚合表示一种弱的…

ThingsBoard版本控制配合Gitee实现版本控制

1、概述 2、架构 3、导出设置 4、仓库 5、同步策略 6、扩展 7、案例 7.1、首先需要在Giitee上创建对应同步到仓库地址 ​7.2、giit仓库只能在租户层面进行配置 7.3、 配置完成后:检查访问权限。显示已成功验证仓库访问!表示配置成功 7.4、添加设…

”数组指针变量与函数指针变量“宝典

大家好呀,我又来啦!最近我很高效对不对,嘿嘿,被我自己厉害到了。 这一节的内容还是关于指针的,比上一期稍微有点难,加油!!! 点赞收藏加关注,追番永远不迷路…

AI大事记(持续更新)

文章目录 前言 一、人工智能AI 1.基本概念 2.相关领域 2.1基础设施 2.2大模型 2.3大模型应用 二、大事记 2024年 2024-05-14 GPT-4o发布 2024-02-15 Sora发布 2023年 2023-03-14 GPT-4.0发布 2022年 2022-11-30 ChatGPT发布 总结 前言 2022年11月30日openai的…

从零开始学习Linux(6)----进程控制

1.环境变量 环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数,我们在编写C/C代码时,链接时我们不知道我们链接的动态静态库在哪里,但可以连接成功,原因是环境变量帮助编译器进行查找,环境变量通常具有…

QT中C端关闭导致S端崩溃问题

在实现多线程C/S通信时,有一个bug卡了我好久——当有一个C端关闭时,S端会崩溃。 经过一条条函数语句的筛查,终于找到问题出在哪里: 我通过类QList和迭代器来存储、访问C端链接的socket,而我在deleteSocket中delete迭…

【农业期刊】转基因作物的利弊分析

摘要概述1 转基因作物的优越性1.1 被修饰生物体的基因的遗传具有稳定性1.2 减少除草剂和农药用量1.3 资源可再生,符合可持续发展观念1.4 改生存环境、增产增收解决人类温饱问题 2 转基因作物的带来的不利影响2.1 影响农业种植制度2.2 转基因技术带来的基因污染2.2.1…

【爬虫之scrapy框架——尚硅谷(学习笔记two)--爬取电影天堂(基本步骤)】

爬虫之scrapy框架--爬取电影天堂——解释多页爬取函数编写逻辑 (1)爬虫文件创建(2)检查网址是否正确(3)检查反爬(3.1) 简写输出语句,检查是否反爬(3.2&#x…

Codeforces Round 920 (Div. 3) D. Very Different Array (贪心)

Petya 有一个由 n n n 个整数组成的数组 a i a_i ai​ 。他的弟弟 Vasya 很羡慕,决定自己也做一个 n n n 个整数的数组。 为此,他找到了 m m m 个整数 b i ( m ≥ n ) b_i ( m≥n ) bi​(m≥n),现在他想从中选择一些 n n n 个整数并按…

电力系统潮流计算的计算机算法(一)——网络方程、功率方程和节点分类

本篇为本科课程《电力系统稳态分析》的笔记。 本篇为这一章的第一篇笔记。下一篇传送门。 实际中的大规模电力系统包含成百上千个节点、发电机组和负荷,网络是复杂的,需要建立复杂电力系统的同一潮流数学模型,借助计算机进行求解。 简介 …

免费Premiere模板,几何图形元素动画视频幻灯片模板素材下载

Premiere Pro模板,几何图形元素动画视频幻灯片模板 ,组织良好,易于自定义。包括PDF教程。 项目特点: 使用Adobe Premiere Pro 2021及以上版本。 19201080全高清。 不需要插件。 包括帮助视频。 免费下载:https://prmu…

Fabric实现多GPU运行

官方的将pytorch转换为fabric简单分为五个步骤: 步骤 1: 在训练代码的开头创建 Fabric 对象 from lightning.fabric import Fabricfabric Fabric() 步骤 2: 如果打算使用多个设备(例如多 GPU),就调用…

NIO使用NIO传输图片

相比于传统的阻塞IO,NIO提供了一种更灵活和高效的 I/O 操作方式,NIO 提供的非阻塞式的 I/O 操作,使得一个单独的线程可以管理多个通道(Channel),从而更好地处理并发连接和大量的 I/O 操作。 1. 核心组件 …