Vue2响应式原理分析(数据代理与数据劫持)

news2024/11/19 15:17:21

综述:

  • 我们都知道,每个Vue的应用都是通过new一个Vue构造函数从而创造出来一个vm实例对象,el(elect)配置项为通过id选择器#root选择index页面中的根dom元素进行绑定,data配置项则为vue模板中用到的源数据。

  • Vue实例在创建时,会接收data对象,并遍历此对象所有的属性,并使用Object.defineProperty将属性全部转为getter/setter,以便追踪属性的变化(obs)。当用户在View层进行操作时,ViewModel能感知到变化并对Model层的数据进行更新,反之亦然。

数据代理:

  • 数据代理即为通过操作对象a来直接触碰对象b达到修改对象b的目的的操作。

  • 在Vue响应式原理中,数据代理则体现在了data配置项通过一系列操作(下文中会分析)赋到了vm实例的_data属性上,然后vm对_data做了代理,即通过Object.defineProperty为vm实例响应式地添加了_data中的属性,从而使Vue模板中不必使用this._data.name来使用,直接使用this.name即可。(Ps:凡是vm实例身上的属性,在Vue模板中均可直接使用,即插值语句{{name}}即可)

  • 而在某种意义上_data与data相同。

  

tips:
  • 一旦data中数据发生改变,那么页面中用到该数据的地方自动更新。

  • _data代理了data,vm代理了_data。

  • 通过defineProperty()方法为vm添加_data中有的属性,再提供setter/getter。

  • 疑点:data经加工后vm._data===data的原因,修改data属性能够重新渲染页面的原因。

  • 原数据data已经被obs劫持,只能通过obs访问。

  • _data里面的属性已经变成访问器属性。

  • _data直接赋值new Vue时传入的data,所以指向同一个地址,二者无区别。

数据劫持:

        上文中提到某种意义上data===_data,这里将介绍数据代理图示中黄色线中所做的操作。

  • 首先data代表vm实例配置项中的源数据,其需要经过加工后,赋给vm._data,所以说二者相同。

  •  至于是如何加工的,下图中的代码做了模拟,用到了观察者对象。

  • 首先data模拟的是未经加工的源数据,将data传入了观察者对象(即obs)的构造函数作为参数(即obj)。传入的为对象data,为其地址。

 
tips:    

        在Java中,函数参数传递的是对象的引用(内存地址),而不是对象本身。当一个对象作为参数传递给一个函数时,实际上是将对象的引用(内存地址)传递给了函数,函数中对该对象的操作会影响到原始对象。因此,在函数内部对传递的对象进行修改时,会影响到原始对象的状态。

       由此,下文中obs,data,._data操作的为同一块内存,故data即为._data

  • 在观察者对象(即obs)中所作的操作就是把obj(即传入的data源数据)的所有的属性名提取出来,为这个obs通过Object.defineProperty的形式响应式地(即getter、setter)添加data中的所有属性(若有深层对象则递归添加)。

  • 现在这个obs身上有了data中的所有属性及其响应式。

  • 之所以采用obs,是为了避免递归死循环。

  • 在下图代码中,然后就是将这个构造好的obs连续赋给data及vm._data(实际中为引用传参)

  • 在此时,若._data属性值修改,很明显将触发对应属性匹配的setter,而这个setter具有执行解析模板、生成虚拟dom、新旧dom的diff算法对比、生成新页面的功能逻辑。

  • 而数据劫持就是体现在这个setter的实际操作中。

  • 在某种意义上,观察者obs相当于一个辅助对象。

  • 在下图中可以看到,._data身上属性的setter和getter,其对源data通过obs套了一层代理,系统命名为reactiveSetter和reactiveGetter,因为其中封装了更新页面的逻辑操作,所以不同。

  • 而且可以看到,._data实际上即为Observer对象,即._data中属性改动将触发Setter渲染页面。

  • 当._data中任意一个reactiveSetter被触发后, 都会使Vue重新解析页面,所以说属性修改后页面重新解析的关键在于Setter。

Vue响应式整体流程: 

  • Vue框架是一个MVVM框架。

(详见我的上一篇博文)MVVM模型

  •   VM即为我们new出来的实例对象,M即为Model(data源数据),V即为View视图(Vue模板template) 。

  • 简而言之,就是在Vue中,ViewModel就是Vue实例。Vue实例在创建时,会接收data对象,并遍历此对象所有的属性,并使用Object.defineProperty将属性全部转为getter/setter,以便追踪属性的变化(obs)。当用户在View层进行操作时,ViewModel能感知到变化并对Model层的数据进行更新,反之亦然。

DOM Listeners:
  • DOM Listeners是对DOM结构进行监听,若发生数据改动则通过DOM listenersDOM监听器将数据传到Model中。

  • 即当vm身上的根属性发生改动(即DOM结构发生改变)后,由于vm对其属性._data做了一层数据代理,其对根属性的改动将通过vm身上的该根属性对应的setter来实现对._data中的对应属性的改动,而._data中属性改动又将通过obs传导到Model中。

Data Bindings:
  • Data Bindings是把Model的数据通过Data Bindings数据绑定送到Vue的模板实例对象上。

  • 即data源数据通过obs传导到._data中,一般情况下vm实例又对._data进行了代理,从而通过vm实例对._data的代理实现了将Model(data)中传来的数据绑定送到Vue模板实例对象的操作。

  • 又因为使用Object.defineProperty,故实现的是使用getter和setter的数据双重绑定操作。

  •  改属性页面变化原理大致如下图所示:

(其中Observer的setter与getter即为上文中提到的reactiveGetter/reactiveSetter。)

 

  •  以下代码为简单的响应式模拟(Object.defineProperty应用):
//源数据
let person = {
	name:'张三',
	age:18
}
//模拟Vue2中实现响应式
let p = {}
Object.defineProperty(p,'name',{
	configurable:true,
	get(){ //有人读取name时调用
		return person.name
	},
	set(value){ //有人修改name时调用
		console.log('有人修改了name属性,我发现了,我要去更新界面!')
		person.name = value
	}
})
Object.defineProperty(p,'age',{
	get(){ //有人读取age时调用
		return person.age
	},
	set(value){ //有人修改age时调用
		console.log('有人修改了age属性,我发现了,我要去更新界面!')
		person.age = value
	}
})

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

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

相关文章

python 层次分析(AHP)

文章目录 一、算法原理二、案例分析2.1 构建指标层判断矩阵2.2 求各指标权重2.2.1 算术平均法(和积法)2.2.2 几何平均法(方根法) 2.3 一致性检验2.3.1 求解最大特征根值2.3.2 求解CI、RI、CR值2.3.3 一致性判断 2.4 分别求解方案层…

算法沉淀——FloodFill 算法(leetcode真题剖析)

算法沉淀——FloodFill 算法 01.图像渲染02.岛屿数量03.岛屿的最大面积04.被围绕的区域05.太平洋大西洋水流问题06.扫雷游戏07.衣橱整理 Flood Fill(泛洪填充)算法是一种图像处理的基本算法,用于填充连通区域。该算法通常从一个种子点开始&am…

【DDD】学习笔记-薪资管理系统的测试驱动开发2

测试驱动开发的过程 满足简单设计并编写新的测试 当代码满足重用性和可读性之后,就应遵循简单设计的第四条原则“若无必要,勿增实体”,不要盲目地考虑为其增加新的软件元素。这时,需要暂时停止重构,编写新的测试。 …

2.23数据结构

单向循环链表 创建单向循环链表,创建节点 ,头插,按位置插入,输出,尾删,按位置删除功能 //main.c #include "loop_list.h" int main() {loop_p Hcreate_head();insert_head(H,12);insert_head(…

计算机网络-网络层,运输层,应用层

网络层/网际层 网络层的主要任务包括: 提供逻辑上的端到端通信:网络层负责确定数据的传输路径,使数据能够从源主机传输到目标主机,即实现端到端的通信。数据包的路由和转发:网络层根据目标主机的地址信息&#xff0c…

vue项目使用vue2-org-tree

实现方式 安装依赖 npm i vue2-org-tree使用的vue页面引入 <template><div class"container"><div class"oTree" ><vue2-org-tree name"test":data"data":horizontal"horizontal":collapsable"…

【服务器数据恢复】通过reed-solomon算法恢复raid6数据的案例

服务器数据恢复环境&#xff1a; 一台网站服务器中有一组由6块磁盘组建的RAID6磁盘阵列&#xff0c;操作系统层面运行MySQL数据库和存放一些其他类型文件。 服务器故障&#xff1a; 该服务器在工作过程中&#xff0c;raid6磁盘阵列中有两块磁盘先后离线&#xff0c;不知道是管理…

LabVIEW开发FPGA的高速并行视觉检测系统

LabVIEW开发FPGA的高速并行视觉检测系统 随着智能制造的发展&#xff0c;视觉检测在生产线中扮演着越来越重要的角色&#xff0c;尤其是在质量控制方面。传统的基于PLC的视觉检测系统受限于处理速度和准确性&#xff0c;难以满足当前生产需求的高速和高精度要求。为此&#xf…

【python】yolo目标检测模型转为onnx,及trt/engine模型的tensorrt轻量级模型部署

代码参考&#xff1a; Tianxiaomo/pytorch-YOLOv4: PyTorch ,ONNX and TensorRT implementation of YOLOv4 (github.com)https://github.com/Tianxiaomo/pytorch-YOLOv4这个大佬对于各种模型转化写的很全&#xff0c;然后我根据自己的需求修改了部分源码&#xff0c;稍微简化了…

【区块链】联盟链

区块链中的联盟链 写在最前面**FAQs** 联盟链&#xff1a;区块链技术的新兴力量**联盟链的定义****联盟链的技术架构**共识机制智能合约加密技术身份认证 **联盟链的特点**高效性安全性可控性隐私保护 **联盟链的应用场景****金融服务****供应链管理****身份验证****跨境支付**…

VSCODE include错误 找不到 stdio.h

解决办法&#xff1a; Ctrl Shift P 打开命令面板&#xff0c; 键入 “Select Intellisense Configuration”&#xff08;下图是因为我在写文章之前已经用过这个命令&#xff0c;所以这个历史记录出现在了第一行&#xff09; 再选择“Use gcc.exe ”&#xff08;后面的Foun…

网络原理-TCP/IP(7)

目录 网络层 路由选择 数据链路层 认识以太网 以太网帧格式 认识MAC地址 对比理解MAC地址和IP地址 认识MTU ARP协议 ARP协议的作用 ARP协议工作流程 重要应用层协议DNS(Domain Name System) DNS背景 NAT技术 NAT IP转换过程 NAPT NAT技术的优缺点 网络层 路由…

如何将建筑白模叠加到三维地球上?

​ 通过以下方法可以将建筑白模叠加到三维地球上。 方法/步骤 下载三维地图浏览器 http://www.geosaas.com/download/map3dbrowser.exe&#xff0c;安装完成后桌面上出现”三维地图浏览器“图标。 2、双击桌面图标打开”三维地图浏览器“ 3、点击“建筑白模”菜单&…

基于java(Springboot)学生信息管理和新生报到系统设计与实现

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

康威生命游戏

康威生命游戏 康威生命游戏(Conway’s Game of Life)是康威发明的细胞自动机。 生命游戏有几个简单的规则&#xff1a; 细胞有两种状态&#xff0c;存活或死亡&#xff0c;每个细胞以自身为中心与周围的八格细胞互动。 对于存活的细胞&#xff1a; 当周围的细胞过少(<2)或…

C# cass10 面积计算

运行环境Visual Studio 2022 c# cad2016 cass10 通过面积计算得到扩展数据&#xff0c;宗地面积 &#xff0c;房屋占地面积&#xff0c;房屋使用面积 一、主要步骤 获取当前AutoCAD应用中的活动文档、数据库和编辑器对象。创建一个选择过滤器&#xff0c;限制用户只能选择&q…

C#最优队列最小堆小顶堆大顶堆小根堆大根堆PriorityQueue的使用

最优队列有多种叫法&#xff0c;什么小根堆&#xff0c;大根堆&#xff0c;小顶堆&#xff0c;大顶堆。 队列分多种&#xff0c;线性队列&#xff08;简单队列&#xff09;&#xff0c;循环队列&#xff0c;最优队列等等。 最优队列&#xff0c;可以看作堆叠箱子&#xff0c;…

【深度学习】LoRA: Low-Rank Adaptation of Large Language Models,论文解读

文章&#xff1a; https://arxiv.org/abs/2106.09685 文章目录 摘要介绍LoRA的特点什么是低秩适应矩阵&#xff1f;什么是适应阶段&#xff1f;低秩适应矩阵被注入到预训练模型的每一层Transformer结构中&#xff0c;这一步是如何做到的&#xff1f; 摘要 自然语言处理的一个重…

vue video 多个视频切换后视频不显示的解决方法

先说一下我这边的需求是视频需要轮播&#xff0c;一个人员有多个视频&#xff0c;左右轮播是轮播某个人员下的视频&#xff0c;上下切换是切换人员。 vue 代码 <el-carouselindicator-position"none"ref"carousel"arrow"always":interval&qu…

CSS 面试题汇总

CSS 面试题汇总 1. 介绍下 BFC 及其应 参考答案&#xff1a; 参考答案&#xff1a; 所谓 BFC&#xff0c;指的是一个独立的布局环境&#xff0c;BFC 内部的元素布局与外部互不影响。 触发 BFC 的方式有很多&#xff0c;常见的有&#xff1a; 设置浮动overflow 设置为 auto、scr…