深入底层——浅谈Vue2和Vue3的响应式数据实现原理
创始人
2025-05-30 04:00:27
0

深入底层——浅谈Vue2和Vue3的响应式数据实现原理

  • 1、Vue2响应式数据存在的问题
  • 2、Vue2为什么监测不到属性变更
  • 3、Vue3是否存在该问题
  • 4、Vue3是如何做数据响应式的
  • 5、拓展
    • 5.1、Proxy代理对象
    • 5.2、Reflect反射对象
  • 6、总结

1、Vue2响应式数据存在的问题

在vue2当中是如何做到更改数据从而页面进行刷新数据的呢?先看底层原理

📝 原理:在vue2中利用的是原生js下边的Object.defineProperty()进行数据劫持,在通过里面的getter和setter方法,进行查看和数据的修改,通过发布、订阅者模式进行数据与视图的响应式。

在进行Vue2的开发过程当中很容易会发现会存在几个问题,那么就是新增、删除对象的属性,以及直接通过对数组的索引值进行修改是不会触发页面刷新的,我们可以通过以下的例子来看一下。



这个问题大多数的Vue2开发者都知道了,这里简单说明一下,针对于直接新增、删除对象属性以及根据数组的索引修改值,都需要通过this.$set 或者 this.$delete 进行操作,或者直接再引入一遍vue,通过vue.set 或者 vue.delete 进行操作。对应Vue2的文档说明:深入响应式原理

2、Vue2为什么监测不到属性变更

在vue官方文档当中有这么一段话进行说明:

📝 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty 把这些 property 全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

⚡️ For example 接下来研究一下为什么监测不到属性变更,

        let person = {name: '张三',}let p = {}Object.defineProperty(p, 'name', {configurable: true,get() {return person.name},set(value) {console.log('name被修改,将更新页面')person.name = value}})

这里简单实现对name的响应式,直接操作p,可以发现,当对p进行新增属性和删除属性的时候,虽然p的值已经被改变了,但是其没有触发到set方法,也就是说这个时候页面不会进行响应更新,基于这一点Vue2当中就提供了 $set$delete 用来做数据响应

在这里插入图片描述

3、Vue3是否存在该问题

答案是很显然的,在vue3当中已经对这个问题进行了处理,我们可以看这个官方文档是如何描述的:Vue 中的响应性是如何工作的

📝 在 JavaScript 中有两种劫持 property 访问的方式:getter / setters 和 Proxies。Vue 2 使用 getter / setters 完全是出于支持旧版本浏览器的限制。而在 Vue 3 中则使用了 Proxy 来创建响应式对象,仅将 getter / setter 用于 ref。

总结: vue2之所以会出现那个问题,是因为Vue2做响应式还是采用的 Object.defineProperty,这是为了兼容ES6之前的浏览器及版本,但是在ES6之后,ES6新增了一个Proxy代理对象,而对于Vue3来说,Vue3.0在2019年就发布了,自然会舍弃 Object.defineProperty 而采用 Proxy 代理对象来实现响应式

4、Vue3是如何做数据响应式的

⚡️ For example 接下来研究一下Vue3实现的底层Proxy代理是如何做的

        let person = {name: '张三',age: 18}let proxy = new Proxy(person, {get(target, propName) {console.log('属性读取 ====', propName)// return target[propName]return Reflect.get(target, propName)},set(target, propName, value) {console.log('属性修改 ====', propName, '  修改后值 ', value)// return target[propName] = valuereturn Reflect.set(target, propName, value)},deleteProperty(target, propName) {console.log('删除属性', propName)// return delete target[propName]return Reflect.deleteProperty(target, propName)}})

✏️ 对于Vue3实现数据响应式还是要归功于ES6新提供的Proxy代理对象,这是因为在代理对象当中可以对整个对象的增删改查的操作都进行拦截,一旦被拦截到了之后Vue3就可以对拦截之后进行页面更新完成数据响应。

在这里插入图片描述
在代码当中可以发现,在Proxy代理对象当中对get、set方法就可以获取到需要修改的对象的对象名称、属性、值这些,只需要直接 对象.属性=值 即可,为什么还要使用一个Reflect这不是麻烦吗?🔖

这是因为使用反射对象用来代替Object,⚡️ For example 当使用 Object.defineProperty 来进行控制更改时,一旦错误的对同一属性进行操作,代码直接报错,这对于底层框架来说是很不好的 ,而相同的代码将 Object 换成 Reflect 是不会出现错误的,而使用Reflect会返回一个是否操作成功的标识,后续只需要对该标识进行判断即可,大程度上避免了报错以及报错后的try catch 处理

Object.defineProperty(person, 'c', {get() {return 4}
})Object.defineProperty(person, 'c', {get() {return 5}
})

5、拓展

5.1、Proxy代理对象

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

MDN Proxy对象说明:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

语法

const p = new Proxy(target, handler)

参数

target
要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

5.2、Reflect反射对象

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同。Reflect 不是一个函数对象,因此它是不可构造的。

MDN Reflect对象说明:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

6、总结

在这里插入图片描述

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
JAVA多线程知识整理 Java多线程基础 线程的创建和启动 继承Thread类来创建并启动 自定义Thread类的子类&#...
【洛谷 P1090】[NOIP... [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G ...
国民技术LPUART介绍 低功耗通用异步接收器(LPUART) 简介 低功耗通用异步收发器...
城乡供水一体化平台-助力乡村振... 城乡供水一体化管理系统建设方案 城乡供水一体化管理系统是运用云计算、大数据等信息化手段࿰...
程序的循环结构和random库...   第三个参数就是步长     引入文件时记得指明字符格式,否则读入不了 ...
中国版ChatGPT在哪些方面... 目录 一、中国巨大的市场需求 二、中国企业加速创新 三、中国的人工智能发展 四、企业愿景的推进 五、...
报名开启 | 共赴一场 Flu... 2023 年 1 月 25 日,Flutter Forward 大会在肯尼亚首都内罗毕...
汇编00-MASM 和 Vis... Qt源码解析 索引 汇编逆向--- MASM 和 Visual Studio入门 前提知识ÿ...
【简陋Web应用3】实现人脸比... 文章目录🍉 前情提要🌷 效果演示🥝 实现过程1. u...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
windows安装JDK步骤 一、 下载JDK安装包 下载地址:https://www.oracle.com/jav...
分治法实现合并排序(归并排序)... 🎊【数据结构与算法】专题正在持续更新中,各种数据结构的创建原理与运用✨...
在linux上安装配置node... 目录前言1,关于nodejs2,配置环境变量3,总结 前言...
Linux学习之端口、网络协议... 端口:设备与外界通讯交流的出口 网络协议:   网络协议是指计算机通信网...
Linux内核进程管理并发同步... 并发同步并发 是指在某一时间段内能够处理多个任务的能力,而 并行 是指同一时间能够处理...
opencv学习-HOG LO... 目录1. HOG(Histogram of Oriented Gradients,方向梯度直方图)1...
EEG微状态的功能意义 导读大脑的瞬时全局功能状态反映在其电场结构上。聚类分析方法一致地提取了四种头表面脑电场结构ÿ...
【Unity 手写PBR】Bu... 写在前面 前期积累: GAMES101作业7提高-实现微表面模型你需要了解的知识 【技...