当前位置: 首页 > ops >正文

vue的双向数据绑定

一、Vue2 的响应式原理

1. 底层依赖:Object.defineProperty

  • Vue2 在 initData 阶段,会遍历 data 对象,用 Object.defineProperty 给每个属性加上 getter / setter

  • getter:依赖收集 → 当模板渲染读取属性时,把当前的渲染函数 Watcher 收集到依赖中。

  • setter:派发更新 → 当数据变化时,通知 Dep 里收集的 Watcher 重新执行更新。

2. 特点

  • 能拦截 对象已有属性 的读写。

  • 对于 新增属性 / 删除属性 无法检测,只能用 Vue.set / Vue.delete

  • 数组 的监听有限:重写了数组的 7 个变更方法(push、pop、shift、unshift、splice、sort、reverse),但无法监听通过下标直接修改数组元素。

二、Vue3 的响应式原理

1. 底层依赖:Proxy

  • Vue3 使用 Proxy 包裹整个对象,统一拦截 对象所有操作(读、写、删、in 判断、遍历等)。

  • 可以拦截对象的 内部方法(内部方法 = ECMAScript 规范里的 [[Get]] [[Set]] [[Delete]] [[HasProperty]] 等)

2. 常见拦截方法

  • get(target, key, receiver) → 依赖收集。

  • set(target, key, value, receiver) → 派发更新。

  • deleteProperty(target, key) → 删除属性时触发更新。

  • has(target, key)in 操作符拦截。

  • ownKeys(target)for...inObject.keys 拦截。

3. 特点

  • 可以监听 新增 / 删除属性

  • 可以监听 数组下标修改

  • 能对 MapSet 等原生集合类型进行响应式处理。

  • 不需要像 Vue2 那样“递归遍历所有属性”,只有在真正访问属性时才递归代理(懒代理)。


🔹 三、框架应用层面

  1. Vue2 (defineProperty)

    • 只能拦截对象已有属性的 读写

    • 其他内部操作(比如 indelete、遍历)拦截不了。

  2. Vue3 (Proxy)

    • 可以拦截对象的 所有基本操作,包括读写、删除、判断、遍历。

    • 响应式系统更健壮、能力更强。


🔹 四、Vue2 vs Vue3 对比总结

对比点Vue2 (Object.defineProperty)Vue3 (Proxy)
拦截范围仅限属性读写支持读写、删除、in、遍历等所有操作
新增/删除属性不能监听,需 Vue.set / Vue.delete原生支持
数组监听只能通过重写方法,不能拦截下标修改可直接监听下标修改
嵌套对象初始化时递归遍历,性能差访问时懒代理,性能好
Map/Set不支持支持
性能初始化慢(深度递归)初始化快(按需代理)

五、面试回答示例(结合应用层+底层原理)

“在 Vue2 里,响应式是通过 Object.defineProperty 来实现的,本质上是给对象已有属性添加 getter/setter,用来做依赖收集和派发更新。但它有局限,比如不能监听新增/删除属性,对数组也只能通过方法重写来监听。

Vue3 则是基于 Proxy 实现的,它可以拦截对象的所有内部操作,比如 get/set/delete/has/ownKeys 等,所以不仅能监听属性读写,还能监听新增删除、数组下标修改、for...in 遍历等操作。同时 Vue3 对象是懒代理,只有在访问时才递归代理,性能更优,也支持 Map/Set 这类新数据结构。

所以从框架应用层面看,Vue2 的双向数据绑定只能拦截‘现有属性的读写’,而 Vue3 则能拦截对象的基本方法/内部方法,响应式能力更强。”

  • 左边是 Vue2 响应式原理(基于 Object.defineProperty

  • 右边是 Vue3 响应式原理(基于 Proxy

可以清晰看到:

  • Vue2 需要遍历属性,getter 收集依赖、setter 派发更新;

  • Vue3 直接通过 Proxy 拦截各种操作,依赖收集和派发更新都集中到 Effect


笔试手写:

🔹 Vue2 响应式原理 (Object.defineProperty)

data↓Object.defineProperty(遍历每个属性)↓┌─────────── getter ───────────┐│ 读取数据 → 依赖收集 (Dep)     │└──────────────────────────────┘┌─────────── setter ───────────┐│ 修改数据 → 通知 Watcher 更新 │└──────────────────────────────┘↓视图更新👉 关键点:只能拦截“已有属性”,新增/删除属性和数组下标改动监听不到。

Vue3 响应式原理 (Proxy)

 data

Proxy(代理整个对象)

┌─────────── get ───────────┐
│ 读取属性 → 依赖收集 (Effect)│
└────────────────────────────┘
┌─────────── set ───────────┐
│ 修改属性 → 触发更新         │
└────────────────────────────┘
┌──────── delete/has/keys ──┐
│ 删除/判断/遍历 → 可拦截    │
└────────────────────────────┘

组件更新
关键点:能拦截几乎所有操作(新增/删除/遍历/数组下标/Map/Set 等

🔹 面试小技巧

  • 如果面试官要你“画个图说明”,就用这个 ASCII 简版,既能表现出流程,也直观体现了 Vue2/3 的区别。

  • 如果他继续问深一点(比如 Dep / Effect 是怎么实现的),就说 Vue 内部通过 依赖收集容器(Dep/ReactiveEffect) 把响应式数据和视图更新关联起来,数据变 → 通知依赖 → 触发渲染。

http://www.xdnf.cn/news/18102.html

相关文章:

  • 【DL学习笔记】损失函数各个类别梳理
  • Go并发编程-goroutine
  • Docker小游戏 | 使用Docker部署文字风格冒险网页小游戏
  • 【计算机视觉与深度学习实战】05计算机视觉与深度学习在蚊子检测中的应用综述与假设
  • wait / notify、单例模式
  • TDengine `count_window` 指定列计数功能用户手册
  • 密码管理中随机数安全修复方案
  • 【金融数据分析】用Python对金融产品价格进行时间序列分解
  • JVM 面试精选 20 题
  • MyCAT完整实验报告
  • 音频分类模型笔记
  • 集成电路学习:什么是Face Detection人脸检测
  • CentOS 7.9 部署 filebrowser 文件管理系统
  • 动态规划:入门思考篇
  • 【完整源码+数据集+部署教程】海洋垃圾与生物识别系统源码和数据集:改进yolo11-RVB
  • 第一阶段C#基础-15:面向对象梳理
  • nsfp-
  • 《Unity Shader入门精要》学习笔记二
  • 多数据源 Demo
  • python 数据拟合(线性拟合、多项式回归)
  • WPF 打印报告图片大小的自适应(含完整示例与详解)
  • quic协议与应用开发
  • 实战架构思考及实战问题:Docker+‌Jenkins 自动化部署
  • [Oracle数据库] Oracle 进阶应用
  • 基于 ONNX Runtime 的 YOLOv8 高性能 C++ 推理实现
  • 网络间的通用语言TCP/IP-网络中的通用规则2
  • CMakeLists.txt 学习笔记
  • Java中的128陷阱:深入解析Integer缓存机制及应对策略
  • 深度解析阿里巴巴国际站商品详情 API:从接口调用到数据结构化处理
  • 8.18决策树