news 2026/6/10 2:17:00

【vue】通俗易懂的剖析vue3的响应式原理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【vue】通俗易懂的剖析vue3的响应式原理

要搞懂Vue3的响应式原理,咱们先抛开专业术语,用奶茶店接单的生活化例子打底,再拆解核心逻辑,最后用简单代码模拟,保证一看就懂。

核心目标:数据变,页面/逻辑自动更

Vue3响应式的本质就是:当你修改数据时,所有用到这个数据的地方(比如页面显示、计算属性、watch)会自动更新

就像奶茶店:

  • 顾客(数据)点了「珍珠奶茶」(数据值);
  • 后厨(页面/计算属性)要按这个要求备料;
  • 顾客改要求(改数据)为「芋圆奶茶」,后厨不用你喊,自动换料(自动更新)。

第一步:给数据装「管家」—— Proxy代理

Vue3之所以能“感知”数据变化,核心是给数据套了一层「代理(Proxy)」,这个代理就像奶茶店的前台管家:不管是“看数据”(读)还是“改数据”(写),都必须经过它。

对比Vue2(为啥换Proxy?)

Vue2用的是Object.defineProperty,只能监听对象的已有属性,比如:

  • 改数组下标(arr[0] = 1)监听不到;
  • 给对象加新属性(obj.newKey = 1)监听不到。

而Proxy是“全方位监听”,能覆盖对象/数组的所有操作(新增、删除、改下标都能感知)。

通俗理解Proxy

假设你有个数据:

constdata={toppings:'珍珠'}

给它套上Proxy后,就像这样:

// 管家(Proxy)constproxyData=newProxy(data,{// 读数据时触发(比如页面渲染用data.toppings)get(target,key){console.log('有人看了',key,'的值');returntarget[key];// 把值返回},// 改数据时触发(比如data.toppings = '芋圆')set(target,key,value){console.log('有人改了',key,'的值,新值是',value);target[key]=value;// 把新值存进去returntrue;}});

此时你操作proxyData.toppings,管家都会立刻知道:

console.log(proxyData.toppings);// 打印:有人看了 toppings 的值 → 珍珠proxyData.toppings='芋圆';// 打印:有人改了 toppings 的值,新值是 芋圆

第二步:记下来「谁用到了数据」—— 依赖收集

管家知道了“谁看/改数据”还不够,得记下来:哪些地方用到了这个数据(比如页面渲染、计算属性),这些“地方”就是「依赖」。

依赖收集的时机

只有当「读数据」时(比如页面首次渲染、计算属性执行),管家才会收集依赖——就像顾客点单时,管家把“顾客A要珍珠奶茶”记在订单本上。

依赖存哪?(简单版容器)

Vue3用三层容器存依赖,咱们简化理解:

targetMap(WeakMap)→ 存「响应式对象」对应的依赖表 └ depsMap(Map)→ 存「对象属性」对应的依赖集合 └ dep(Set)→ 存「用到这个属性的所有副作用函数」
  • 副作用函数:凡是用到响应式数据的函数(比如页面渲染函数、effectwatch回调),执行它会产生“副作用”(比如改变页面)。
  • 用Set是为了避免重复:比如同一个数据在页面用了两次,只需要更新一次。

第三步:数据变了,喊「依赖」更新—— 触发更新

当你改数据时(管家的set触发),管家会翻订单本,找到所有用到这个数据的依赖,挨个通知它们“数据变了,快更!”——就像顾客改配料,管家喊后厨:“A和B的订单都换成芋圆!”。

完整流程(奶茶店版)

  1. 初始化:给{ toppings: '珍珠' }套上Proxy管家;
  2. 首次渲染:页面要显示{{ toppings }},读toppings→ 管家触发get→ 把“页面渲染函数”记到toppings的依赖集合里;
  3. 修改数据:改toppings = '芋圆'→ 管家触发set→ 找到依赖集合里的“页面渲染函数” → 执行函数 → 页面更新为“芋圆”。

补充:Ref是干啥的?

Proxy只能代理对象/数组,没法代理字符串、数字等基本类型(比如let age = 18)。

所以Vue3搞了ref:把基本类型包成「带value属性的对象」,再代理这个对象的value属性。

constage=ref(18);// 实际是 { value: 18 }age.value=20;// 改value才会触发更新

模板里不用写.value,是因为Vue自动帮你“解包”了(比如<div>{{ age }}</div>)。

用代码模拟Vue3响应式核心

下面的代码去掉了Vue3的复杂逻辑,只保留核心,能直观看到“收集依赖→触发更新”的过程:

// 1. 存储依赖的容器:targetMap → depsMap → depconsttargetMap=newWeakMap();// 2. 收集依赖(track:追踪)functiontrack(target,key){// 找当前对象的依赖表letdepsMap=targetMap.get(target);if(!depsMap){depsMap=newMap();targetMap.set(target,depsMap);}// 找当前属性的依赖集合letdep=depsMap.get(key);if(!dep){dep=newSet();// Set避免重复依赖depsMap.set(key,dep);}// 把当前的副作用函数加入依赖dep.add(activeEffect);}// 3. 触发依赖(trigger:触发)functiontrigger(target,key){constdepsMap=targetMap.get(target);if(!depsMap)return;constdep=depsMap.get(key);if(dep){// 执行所有依赖的副作用函数dep.forEach(effect=>effect());}}// 4. 全局变量:当前正在执行的副作用函数letactiveEffect;// 5. 注册副作用函数(比如页面渲染、watch)functioneffect(fn){activeEffect=fn;fn();// 执行一次,触发track收集依赖activeEffect=null;}// 6. 模拟reactive:创建响应式对象functionreactive(target){returnnewProxy(target,{get(target,key){constres=Reflect.get(target,key);track(target,key);// 读数据时收集依赖returnres;},set(target,key,value){constres=Reflect.set(target,key,value);trigger(target,key);// 改数据时触发更新returnres;}});}// 测试:模拟页面渲染constdata=reactive({toppings:'珍珠'});// 注册副作用函数(模拟页面渲染)effect(()=>{console.log('页面更新:奶茶配料='+data.toppings);});// 改数据,触发更新data.toppings='芋圆';// 打印:页面更新:奶茶配料=芋圆data.toppings='椰果';// 打印:页面更新:奶茶配料=椰果

关键总结

Vue3响应式的核心就3步:

  1. 代理拦截:用Proxy包裹数据,拦截读(get)和写(set);
  2. 收集依赖:读数据时(get),把用到数据的副作用函数记下来;
  3. 触发更新:改数据时(set),执行所有记下来的副作用函数。

额外补充:

  • reactive:处理对象/数组,默认深响应(嵌套对象也能监听);
  • ref:处理基本类型,本质是代理{ value: 原值 }
  • shallowReactive/shallowRef:浅响应,只监听第一层属性;
  • WeakMap:依赖容器用它是为了内存友好(数据销毁后自动回收依赖,不泄漏)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 17:39:33

基于Markdown文档管理ACE-Step项目:提升开源协作效率

基于Markdown文档管理ACE-Step项目&#xff1a;提升开源协作效率 在AI生成内容&#xff08;AIGC&#xff09;浪潮席卷创意产业的今天&#xff0c;音乐创作正经历一场静默却深刻的变革。过去&#xff0c;一段高质量的原创配乐往往需要专业作曲家耗费数小时打磨&#xff1b;而如今…

作者头像 李华
网站建设 2026/6/9 17:42:13

基于Wan2.2-T2V-A14B的AI影视创作工作流优化策略

基于Wan2.2-T2V-A14B的AI影视创作工作流优化策略 在短视频爆发、广告迭代加速的今天&#xff0c;一支30秒的品牌宣传片从创意到成片动辄需要数周时间——脚本打磨、分镜绘制、实拍调度、后期合成……每一个环节都像齿轮一样咬合紧密&#xff0c;但也因此格外脆弱。一旦客户临时…

作者头像 李华
网站建设 2026/6/9 16:07:38

Day36 官方文档的阅读

1. 官方文档的检索方式&#xff1a;github和官网 2. 官方文档的阅读和使用&#xff1a;要求安装的包和文档为同一个版本 3. 类的关注点&#xff1a; 实例化所需要的参数普通方法所需要的参数普通方法的返回值 4. 绘图的理解&#xff1a;对底层库的调用 第一步是实例化这个…

作者头像 李华
网站建设 2026/6/9 16:09:23

ARP扫描工具arp-scan:快速发现局域网设备完整指南

ARP扫描工具arp-scan&#xff1a;快速发现局域网设备完整指南 【免费下载链接】arp-scan The ARP Scanner 项目地址: https://gitcode.com/gh_mirrors/ar/arp-scan ARP扫描工具arp-scan是一款专为网络管理员和安全工程师设计的强大局域网设备发现工具。通过利用ARP协议的…

作者头像 李华
网站建设 2026/6/9 18:35:40

Rust语言+Seed-Coder-8B-Base:系统级编程的智能未来

Rust语言Seed-Coder-8B-Base&#xff1a;系统级编程的智能未来 在现代软件工程中&#xff0c;系统级开发正面临前所未有的挑战——既要保证极致性能与资源效率&#xff0c;又要应对日益复杂的并发逻辑和内存管理。尤其是在操作系统、嵌入式设备、区块链节点等关键场景下&#x…

作者头像 李华
网站建设 2026/6/8 21:56:22

ParsecVDD虚拟显示器完整解决方案:多屏工作新体验

ParsecVDD虚拟显示器完整解决方案&#xff1a;多屏工作新体验 【免费下载链接】parsec-vdd ✨ Virtual super display, upto 4K 2160p240hz &#x1f60e; 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 在当今数字化工作环境中&#xff0c;单一显示器已成为…

作者头像 李华