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

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.dtcms.com/a/337077.html

相关文章:

  • 哪里找最新AI工具官网?如何快速对比ChatGPT替代品?AI工具导航指南 - AIbase
  • 基于Spring Boot+Vue的社区便民服务平台 智慧社区平台 志愿者服务管理
  • [矩阵置零]
  • 快速搭建项目(若依)
  • 【JavaEE】(16) Spring Boot 日志
  • 重温k8s基础概念知识系列四(服务、负载均衡和联网)
  • [免费]基于Python的全国气象数据采集及可视化大屏系统(Flask+request库)【论文+源码+SQL脚本】
  • Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin(2)
  • 你好星识内测,未来是人与AI共创的时代
  • [特殊字符] 什么是 Linux?[特殊字符] 什么是 Shell?[特殊字符] 什么是 Bash? [特殊字符]Linux、Shell、Bash 的关系?
  • 特种行业许可证识别技术:通过图像处理、OCR和结构化提取,实现高效、准确的许可证核验与管理
  • 通过PhotoShop将多张图片整合为gif动画
  • npm设置了镜像 pnpm还需要设置镜像吗
  • Ps 2025 图像编辑 Photoshop(Mac中文)
  • 前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
  • PDF处理控件Aspose.PDF教程:将 PNG 合并为 PDF
  • Arkts加载网页url的pdf发票黑屏问题
  • vscode wsl解决需要用别的用户调试的问题
  • 国产化Excel处理组件Spire.XLS教程:使用 C# 从数据库导出数据到 Excel(含 SQL 示例)
  • Android使用Kotlin协程+Flow实现打字机效果
  • 【内网渗透】CVE-2020-0796 永恒之黑 复现
  • 19.8 《3步实现OPT-6.7B无损量化:用自定义数据集省70%显存,精度仅跌2.3%》
  • (Arxiv-2025)OPENS2V-NEXUS:一个面向主体到视频生成的详细基准与百万规模数据集
  • 设计模式笔记_行为型_迭代器模式
  • 云计算核心技术之容器技术
  • Linux设备树简介
  • LINUX 818 shell:random;for for
  • 电子元器件-电阻终篇:基本原理,电阻分类及特点,参数/手册详解,电阻作用及应用场景,电阻选型及实战案例
  • Docker常见指令速查
  • 矿物分类案例(二)数据填充后使用6种模型训练