vue3 为什么需要toRef和toRefs

为什么在vue3中需要 toRef和toRefs?

先给一个最直接的答案:这是响应式设计语言最底层上的根源缺陷(天生自带)。所以 toRef和toRefs就是为了弥补js语言而不得不打的补丁。

下面深入看一下为什么

一、JS 的值传递机制,破坏了Proxy的拦截

总所周知,js数据类型分为基本数据类型和引用数据类型,基本数据类型的值直接在栈内存中存储而引用数据类型存储在堆中并且变量保存的是地址不是原始值。搞清楚这一点后来看一下 解构的执行逻辑。js中不管对方是基本数据类型还是引用数据类型,解构起到的是搬运操作。

对于基本数据类型:

  • 基本类型直接存储在栈内存(Stack)中,占据固定大小的空间。解构时先得到该值所在位置
  • 然后JS 引擎在栈内存中开辟一块全新的空间,把这个要解构的值复制进去。新变量指向这个新空间。
  • 修改新变量,绝对不会影响源对象中的属性

对于引用数据类型:

  • 引用数据类型存储在堆内存(Heap)中,占据不定大小空间;栈内存只存一个指向堆内存的指针(内存地址)。
  • 解构时引擎取出的是栈中的指针地址(比如 0xFF01)。把这个地址复制给新变量
  • 新变量 b 和源对象属性指向堆内存中的同一块地址。因此修改新变量中数值,源对象中也会变

示例: 对 state 进行解构

js 复制代码
const state = reactive({ count: 0, name: 'Vue' });

const { count, name } = state; 

根据解构原理来说 因为count 和name都是基础数据类型所以解构出来的 count和name 都是新值,所以原来的proxy代理不生效。为了解决这个问题 vue3 引入了toRef 来解决,来看一下简易源码

js 复制代码
class ObjectRefImpl {
  get value() {
    // 每次你访问 .value,我都去源对象上读取最新值
    return this._object[this._key]; 
  }
  set value(newVal) {
    // 每次你设置 .value,我都去修改源对象
    this._object[this._key] = newVal;
  }
}

可以看出使用 toRef后之所以还能够保持响应式得主要原因,toRef返回的根本不是响应式数据,而是一个指向源对象属性的引用

再来看下toRefs

js 复制代码
export function toRefs<T extends object>(object: T): ToRefs<T> {
  // 如果不是 reactive 对象,开发环境会警告,但依然可以工作
  const result: any = Array.isArray(object) ? new Array(object.length) : {};
  
  // 遍历对象的所有 key
  for (const key in object) {
    // 对每个 key 执行 toRef,建立映射
    result[key] = toRef(object, key);
  }
  return result;
}

其实toRefs就是批量执行了toRef,把对象得所有属性变成ref。有了toRefs,我们就能够很方便的构造出usexxx函数

js 复制代码
setup() {
	function useInfo() {
	  const state = reactive({ count: 0, name: 'Vue' });
	  // 返回时用 toRefs 包裹,模板中就可以直接写 {{ count }},无需写 state.count
	  return { ...toRefs(state) };
	}
	const { count, name } = useInfo();
}
相关推荐
IT_陈寒4 分钟前
当Java的hashCode遇上Lombok,我的缓存被全清了
前端·人工智能·后端
工控丫丫31 分钟前
帆软看板中经常使用的公式函数及经常搭的组合
前端·javascript·数据库
jerrywus1 小时前
我用 GPT-6.1-sol 做了台会讲解的 3D 售货机:60 罐饮料,一口没喝上
前端·agent·claude
孟陬2 小时前
Foobar 技术周刊#159:当看不懂代码时,如何高效排障调试。脏页陷阱:一条只读查询,写入数 TB 数据。推测解码:大模型加速利器
前端·人工智能·后端
Zhao-Jichao2 小时前
AI Prompting for Everyone 课程笔记 - P17 图像生成 Imaging Generation
前端
Highcharts.js3 小时前
智能数据分析组件Orbit 正式发布与快速上手体验教程
前端·人工智能·信息可视化·数据分析系统·highcharts·orbit·智能可视化
Dream-Y.ocean3 小时前
鸿蒙PC平台星图遥感适配实战:基于 Electron 壳方案的纯 JavaScript 遥感图像处理引擎开发
javascript·electron·harmonyos
螺丝钉tina4 小时前
[Playwright ][16]Playwright + TypeScript API 自动化测试实战:API测试
前端·javascript·typescript
小天源4 小时前
智叟云集系统 · 架构与职责分层
服务器·前端·数据库
Highcharts.js6 小时前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格