【手写 Vue2.x 源码】第九篇 - 对象数据变化的观测情况

news2025/1/11 18:43:19

一,前言

上篇,主要介绍了数组深层观测的实现,核心几个点如下:

最初仅对数组类型进行了原型方法重写,并未进行递归处理,所以,当时仅实现了数组的单层劫持;

通过对数组进行 observe 递归观测,实现了对数组嵌套结构的劫持(数组中嵌套数组、数组中嵌套对象)

但是,由于 observe 方法对非对象类型不进行处理,所以,数组中的值类型将不会被劫持;

与 Vue2.x 功能进行对比,目前代码仍需实现以下功能:

  • 对象中,老属性变更为对象、数组的情况 - 需对修改值进行深层观测处理
  • 对象中,新增属性的情况 - 需进行说明
  • 数组中,新增对象、数组、普通值的情况 - 需实现数组的方法重写并对修改值进行递归处理

综上,将其划分为两大部分:

  • 对象数据变化:对象中,老属性变更为对象;对象中,新增属性的情况;
  • 数组数据变化:对象中,老属性变更为数组;数组中,新增对象、数组、普通值的情况;

本篇,对象数据变化的观测情况(老属性变更为对象、新增属性的情况)

由于数组的递归劫持尚未实现,故本篇不包含对象老属性变更为数组的情况;

将“对象老属性变更为数组”和“数组数据变化的观测情况”进行合并;

TODO 》》思考了一下:“对象中,老属性变更为数组的情况”应该被放到本篇“对象数据变化的观测情况”一起,理由是:即便此时还没有为对象属性修改为数组做递归观测,也应该被归类为“对象数据变化”,且后续“数组数据”实现递归观测后,这个问题也会一并得到解决;


二,对象中,老属性变更为对象的观测问题

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]} // data 返回一个对象
  }
});

// 将属性 message 由普通值,变更为对象类型
vm.message = { a: 100 }
// 对新增对象属性进行修改
vm.message.a = 200;
// src/observe/index.js#defineReactive

function defineReactive(obj, key, value) {
  observe(value);
  Object.defineProperty(obj, key, {
    get() {
      return value;
    },
    set(newValue) {
      console.log("修改了被观测属性 key = " + key + ", newValue = " + JSON.stringify(newValue))
      if (newValue === value) return
      value = newValue;
    }
  })
}

image.png

1,vm.message = { a: 100 }

将 data 中 message 属性由初始值"Hello Vue",变更为对象类型 { a : 100 }

由于 { a : 100 } 是 data 初始化完成后的新增对象,属于对象中新增对象

而当前版本中的新增对象不会被劫持,也就不会触发视图的更新

2,vm.message.a = 200

由于对象 { a : 100 } 没有被观测,所以修改此对象中的属性时,不会触发视图的更新

三,对象中,老属性变更为对象的观测实现

为了实现新增对象的数据观测,当设置的值为对象时,将此对象继续进行深层观测即可;

// src/observe/index.js#defineReactive

/**
 * 给对象Obj,定义属性key,值为value
 *  使用Object.defineProperty重新定义data对象中的属性
 *  由于Object.defineProperty性能低,所以vue2的性能瓶颈也在这里
 * @param {*} obj 需要定义属性的对象
 * @param {*} key 给对象定义的属性名
 * @param {*} value 给对象定义的属性值
 */
function defineReactive(obj, key, value) {
  observe(value);// 递归实现深层观测
  Object.defineProperty(obj, key, {
    get() {
      return value;
    },
    set(newValue) {
      console.log("修改了被观测属性 key = " + key + ", newValue = " + JSON.stringify(newValue))
      if (newValue === value) return
      // 当值被修改时,通过 observe 实现对新值的深层观测,此时,新增对象将被观测
      observe(newValue);
      value = newValue;
    }
  })
}

输出结果:

image.png

这样,就实现了对象中新增对象的深层观测

同时,对新增对象中的属性再次进行修改时,也能够通过数据劫持实现视图更新了


四,对象中,新增属性的情况

向 message 属性的新增对象 { a:100 } 中,添加一个不存在的属性 b,是否会进行数据劫持?

let vm = new Vue({
  el: '#app',
  data() {
    return { message: 'Hello Vue', obj: { key: "val" }, arr:[1,2,3]}
  }
});

// 属性 message 由“普通值” 变更为 “对象”类型
vm.message = { a: 100 }
// 向新增对象中添加一个不存在的属性
vm.message.b = 200;
// 修改新增属性值
vm.message.b = 300;
之前新增对象时,通过 observe 方法对新增对象进行了深层观测

而此时,向新增对象中添加新属性 b 并不会被劫持,也不会触发任何为其添加数据劫持的逻辑

所以,向新增对象中添加新属性将不会被劫持;

在 Vue2.x 中,为新增对象添加新属性,也是不能实现数据劫持的;

但可以通过 vm.$set 来实现对象中新增属性的数据观测能力;


五,结尾

本篇,主要介绍了数组数据变化的观测情况:

  • 实现了对象老属性值变更为对象、数组时的深层观测处理;
  • 结合实现原理,说明了对象新增属性不能被观测的原因,及如何实现数据观测;

下一篇,数组数据变化的观测情况(对象中,老属性变更为数组;数组中,新增对象、数组、普通值的情况;)

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

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

相关文章

二、Gtk4-GtkApplication and GtkApplicationWindow

1 GtkApplication 1.1 GtkApplication and g_application_run 人们编写编程代码来开发应用程序。什么是应用程序?应用程序是使用库运行的软件,其中包括操作系统、框架等。在GTK 4编程中,GTK应用程序是使用GTK库运行的程序(或可执行程序)。 编写GtkAp…

信创改造,你了解多少?

最近,“信创”一词在IT圈瞬间爆火,那什么是信创?又能带来哪些突破性的改变?跟随佑友一起来详细了解一下… 信创的来源 2016年3月4日,24家专业从事软硬件关键技术研究及应用的国内单位,共同发起成立了一个非…

分布式链路追踪-skywalking入门体验

背景 旁友,你的线上服务是不是偶尔来个超时,或者突然抖动一下,造成用户一堆反馈投诉。然后你费了九牛二虎之力,查了一圈圈代码和日志才总算定位到问题原因了。或者公司内部有链路追踪系统,虽然可以很轻松地通过监控判…

deb dpkg fpm cpack debmake 打包

文章目录deb 简介hello debfpmpreinst postinst prerm postrmcmake cpackdebmakedeb 简介 deb: Linux发行版Debian系列(如Debian, Ubuntu等)的软件包格式, 没有自提取(Self-extracting), 不能直接运行, 需要借助dpkg等安装. Dpkg: Debian Package Manager, Debian包管理器, 中…

Python读取各种形式文件(excel,txt),python基本用法

读取excel,读取结果是dataframe形式。 excelFile ranalyze_search_category.xlsx df pd.DataFrame(pd.read_excel(excelFile)) print(df) 详情:(21条消息) 在Python中使用Pandas.DataFrame对Excel操作笔记一 - 从Excel里面获取说需要的信息_fengqiaoxian的博客-CS…

TensorFlow之模型保存与加载

模型在训练过程中或者在训练之后,模型的执行过程能被保存,也就是,模型能从暂停中恢复以免训练的时间过长。因此,被保存的模型可以被共享,其他人可以重新构建相同的模型。被保存的模型以如下的两种方式进行共享&#xf…

青训营——前端方向练习题(不定项选择题例题)

文章目录 📄前言 PART1 PART2 PART3 PART4 PART5 PART6 PART7 PART8 PART9 📄前言 一共有十八题,题目选项为不定项,有单选,也有多选。 PART1 选择题 1: 下列哪些是 HTML5 的新特性? A…

Android 深入系统完全讲解(3)

3 Zygote 虚拟机的流程,学习方法 说完了 init 的启动过程,我们来说说 Zygote 的启动过程。 这里我们看下整个的步骤,主要完成了: 1 startVM() 创建虚拟机 2 startReg() 注册 JNI 方法 3 preload()预加载通用类,这里主…

【信管7.1】质量与质量管理过程

质量与质量管理过程对于我们的项目管理理论相关的学习来说,质量是除了范围、进度、成本之外的另一个核心内容。还记得我们在学习敏捷的时候讲过的项目管理三角形吗?通过之前的课程,我们已经学完了它的三个支点。接下来,我们就要学…

播客丨关于年终总结,程序员有话说

绘声绘影绘声绘影是网易云信独家打造的一档聚焦行业热点、个人成长方面的播客栏目。栏目希望通过邀请不同背景、不同行业、不同阅历的企业研发、产品、运营等相关岗位负责人作为节目嘉宾,以自身职业视角交流行业洞见和发展前景;以过来人的视角分享在时代…

dfs、bfs搜索题型小结

一、全排列 (1)1199:全排列 原题链接 解析 (2)剪枝思想 满足等式关系的全排列——dfs剪枝 (3)P1088 [NOIP2004 普及组] 火星人 原题链接 解析 二、组合(选与不选)…

web(四)—— CSS基础(选择器进阶、Emmet语法、背景属性、元素显示模式、三大特性)

一、选择器进阶目标:能够理解 复合选择器 的规则,并使用 复合选择器 在 HTML 中选择元素1. 复合选择器1.1 后代选择器:空格作用:根据 HTML 标签的嵌套关系,选择父元素 后代中 满足条件的元素 选择器语法:选…

Maven的安装配置与基本使用

Maven简介: Maven是专门用于管理和构建java项目的工具,它的主要功能有: 提供了一套标准化的项目结构标准化的项目结构: Maven提供了一套标准化的项目结构,所有的IDE使用Maven构建的项目结构完全一样,所有…

【IEEE出版社】人工智能、数据挖掘、机器人、传感等领域SCI,自引率低,对国人友好,评职毕业高分好刊~

1区人工智能类SCI&EI 【出版社】IEEE 【自引率】4.30%(低) 【国人占比】13.40% 【期刊简介】IF:6.5-7.0,JCR1区,中科院3区 【检索情况】SCI&EI 双检,正刊 【参考周期】3-5个月左右录用 【截稿日期】202…

如何彻底关闭Win10自动更新,Win10永久关闭自动更新的方法

如何彻底关闭Win10自动更新?Win10自动更新的问题是很多用户都遇到的问题,很多时候我们关闭了自动更新,过一段时间系统又自动更新了,由于win10自动更新非常顽固,所以我们要从多个地方下手才能永久关闭其自动更新&#x…

Java中几种常量池的区分

文章目录前言了解一下 ldc 指令字符串常量池在 Java 内存区域的哪个位置1.全局字符串池(string pool也有叫做string literal pool)2.class文件常量池(class constant pool)3.运行时常量池(runtime constant pool&#…

干货 | Python的面试题目+答案合集

作为一个 Python 新手,你必须熟悉基础知识。 在本期内容中我们将讨论一些 Python 面试的基础问题和高级问题以及答案,以帮助你完成面试。 包括 Python 开发问题、编程问题、数据结构问题、和 Python 脚本问题。 接下来让我们来深入研究这些问题 Pytho…

AD转换芯片精度计算及校正方法

文章目录前言一、转换精度二、重要参数1.线性误差(INL)和差分线性误差(DNL)2.失调误差和增益误差三、转换校正总结前言 本文对模数转换芯片的精度进行简要介绍,帮助大家正确选型,并介绍了一个基本的ADC转换…

postgresql13+postgis3.2安装教程

postgresql13postgis3.2安装教程 安装postgresql13 安装pg13 pg13安装包 cd /home/soft/pg tar -zxvf postgresql-13.6.tar.gz cd postgresql-13.6# yum -y install -y readline-devel./configure --prefix/usr/local/pgsqlmake -j4make install设置环境变量 vim /etc/pr…

OpenGPT的11种高效用法

1. 问答提示 2. 解释复杂的概念 3. 创作 创作需要尽可能的缩小范围,提出具体的要求,AI会给出更好的答案。 4. 准备面试 5. 教师教案 6. 编码和集成 7. 健身 8. 送礼推荐 9. 翻译 这个甚至不用去演示,openAI的翻译能力非常强大&#xff0c…