news 2026/5/1 11:30:19

Vue3 响应式系统——ref 和 reactive

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3 响应式系统——ref 和 reactive

一、Vue3 响应式系统概述

Vue3 响应式包@vue/reactivity,核心由三部分构成:

数据 (Proxy Object) —— 依赖收集 Track —— 触发更新 Trigger —— Effect 执行更新

核心目标:

  • 拦截读取和设置操作
  • 收集依赖
  • 在数据变化时重新触发相关副作用

主要实现 API:

二、reactive()执行机制

2.1 核心逻辑(核心源码)

function reactive(target) { return createReactiveObject(target, false, mutableHandlers) } function createReactiveObject(target, isReadonly, baseHandlers) { if (!isObject(target)) { return target } if (target already has proxy) return existing proxy const proxy = new Proxy(target, baseHandlers) cache proxy return proxy }

Vue3 用 ​Proxy 拦截对象操作​,比 Vue2 的Object.defineProperty更强(能监听属性增删)。

2.2 reactive 的 handler(简化)

const mutableHandlers = { get(target, key, receiver) { const res = Reflect.get(target, key, receiver) track(target, key) return isObject(res) ? reactive(res) : res }, set(target, key, value, receiver) { const oldValue = target[key] const result = Reflect.set(target, key, value, receiver) if (oldValue !== value) { trigger(target, key) } return result } }

三、依赖收集和触发更新:track()trigger()

Vue 内部维护一个 ​全局的 activeEffect​:

let activeEffect = null function effect(fn) { activeEffect = wrappedEffect(fn) fn() // 执行一次用于收集依赖 activeEffect = null }

每次读取(get)响应式数据时:

function track(target, key) { if (!activeEffect) return const depsMap = targetMap.get(target) || new Map() const dep = depsMap.get(key) || new Set() dep.add(activeEffect) }

当数据被设置(set)时:

function trigger(target, key) { const depsMap = targetMap.get(target) const dep = depsMap?.get(key) dep?.forEach(effect => effect()) }
  • track只在读取时收集依赖
  • trigger只在数据修改时触发 effect 重新执行

四、ref()的设计与区别

4.1ref是什么?

ref()主要用于包装基本类型(对于对象引用类型内部直接调用上面的reactive()):

const count = ref(0)

其结构本质上是:

interface RefImpl { value: T }

源码核心:

function ref(rawValue) { return createRef(rawValue) } function createRef(rawValue) { const refImpl = { _value: convert(rawValue), dep: new Set(), // 区别于reactive引用类型复杂的多层嵌套数据结构封装dep,ref这里直接在实例中存放一个dep来实现 get value() { trackRefValue(refImpl) return refImpl._value }, set value(newVal) { if (hasChanged(newVal, refImpl._value)) { refImpl._value = convert(newVal) triggerRefValue(refImpl) } } } return refImpl }

4.2 ref vs reactive 的本质区别

五、template / setup 中的自动 unwrap

在 Vue 模板中:

<p>{{ count }}</p>

如果count是一个 ref,它会 ​自动解包​,模板中不需要写.value。这是由编译阶段的 transform 实现的。

六、响应式系统执行流程图(简化)

reactive/ref 数据 -> Proxy getter -> track │ effect 注册 │ 数据 setter -> trigger ↓ 重新执行 effect
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 8:18:22

【毕业设计】基于SpringBoot+Mysql的乐器社区网站基于springboot+微信小程序的乐器宣传平台(源码+文档+远程调试,全bao定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/1 9:28:02

SpringAI-本地大模型

1.本地大模型的定义 本地⼤模型&#xff08; Local Large Model &#xff09;是指不依赖于云端计算资源&#xff0c;⽽是部署和运⾏在本地设备上的 ⼤规模⼈⼯智能模型。这些模型通常具有较强的计算能⼒和存储需求&#xff0c;因此通常在⾼性能的本地硬件 &#xff08;如⾼性能…

作者头像 李华
网站建设 2026/5/1 6:52:20

金额计算字段类型用Long,还是BigDecimal更好?

前言 对于从事后端开发的小伙伴来说&#xff0c;可能会遇到金额计算字段的类型&#xff0c;到底该用Long&#xff0c;还是BigDecimal的困扰。 甚至有些公司的架构师跟DBA&#xff0c;有时也会为了金额计算字段的类型而PK。 今天这篇文章专门跟大家一起聊聊这个话题&#xff0c;…

作者头像 李华
网站建设 2026/5/1 7:57:45

【课程设计/毕业设计】基于微信小程序的乐器宣传平台基于springboot+微信小程序的乐器宣传平台【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/5/1 8:02:53

关于3D打印仿血管拓扑结构在散热设计中的应用与优化

&#x1f393;作者简介&#xff1a;科技自媒体优质创作者 &#x1f310;个人主页&#xff1a;莱歌数字-CSDN博客 &#x1f48c;公众号&#xff1a;莱歌数字&#xff08;B站同名&#xff09; &#x1f4f1;个人微信&#xff1a;yanshanYH 211、985硕士&#xff0c;从业16年 从…

作者头像 李华
网站建设 2026/5/1 10:31:07

基于深度学习和熔池图像对的焊缝熔透状态识别【附代码】

✅ 博主简介&#xff1a;擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导&#xff0c;毕业论文、期刊论文经验交流。✅成品或者定制&#xff0c;扫描文章底部微信二维码。(1) 双棱镜单摄像机被动立体视觉系统的设计与熔池图像采集熔化极气体保护焊接过程中&…

作者头像 李华