vue3响应式数据(ref,reactive)详解

ref

概念:

  • 用于创建响应式的基本类型数据(如 string, number, boolean)

  • 也可以用于对象和数组,但更推荐对基本类型使用

  • 返回一个响应式的、可变的 ref 对象,该对象内部通过 .value 属性持有其值

  • 模板中的 ref 属性(如 <div ref="myDiv">)会创建 DOM 元素的引用,这与响应式的 ref 是不同的概念

javascript 复制代码
import { ref } from 'vue'

const count = ref(0) // 创建
console.log(count.value) // 访问
count.value++ // 修改

特点:

  1. 在模板中使用时自动解包,无需 .value

  2. 在响应式对象中使用时自动解包

    javascript 复制代码
    ​
    const state = reactive({
      foo: 1,
      bar: 2
    })
    
    //直接使用即可,不需要state.foo.value++
    ​state.foo++
    console.log(​state.foo)// 2
  3. 适合用于基本类型数据和需要在多处引用的响应式数据

reactive

概念:

  • 用于创建响应式的对象(包括数组)

  • 返回对象的响应式代理

  • 只能用于对象类型(Object, Array, Map, Set 等)

javascript 复制代码
import { reactive } from 'vue'

const state = reactive({
  count: 0,
  name: 'Vue'
}) // 创建
console.log(state.count) // 访问
state.count++ // 修改

特点:

  1. 直接访问和修改属性,不需要 .value

  2. 解构或属性赋值会失去响应性

  3. 适合用于复杂对象和局部状态

toRef 和 toRefs

toRef 和 toRefs 是 Vue3 组合式 API 中用于处理响应式引用的两个实用函数,它们可以帮助我们在解构或传递响应式对象时保持其响应性。

toRef

toRef 用于为响应式对象上的某个属性创建一个 ref 引用,这个 ref 会与源属性保持同步。

javascript 复制代码
import { reactive, toRef } from 'vue'

const state = reactive({
  foo: 1,
  bar: 2
})

// 创建一个与 state.foo 保持同步的 ref
const fooRef = toRef(state, 'foo')

// 修改 ref 会更新原始属性
fooRef.value++
console.log(state.foo) // 2

// 修改原始属性也会更新 ref
state.foo++
console.log(fooRef.value) // 3

toRefs

toRefs 将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向原始对象相应属性的 ref。

简单理解,如图所示:

javascript 复制代码
import { reactive, toRefs } from 'vue'

const state = reactive({
  foo: 1,
  bar: 2
})

const stateRefs = toRefs(state)

// ref 和原始属性保持同步
stateRefs.foo.value++
console.log(state.foo) // 2

state.bar++
console.log(stateRefs.bar.value) // 3

注意事项:

  1. 这两个函数只对响应式对象(reactive 创建)有效,对普通对象无效

  2. 使用解构赋值时,toRefs 可以保持响应性,而直接解构会失去响应性

  3. 对于可能不存在的属性,可以使用 toRef 并提供默认值:

    javascript 复制代码
    const fooRef = toRef(state, 'nonExistent', 'default value')

实际应用:

  1. 基本类型 优先使用 ref

  2. 复杂对象(层级较深) 使用 reactive

  3. 组合式函数返回状态时优先返回 ref,方便解构

  4. 使用 isRef 和 isReactive 进行类型检查

相关推荐
卸任6 小时前
Vibe coding工具使用心得
前端·ai编程
brien97 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance7 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M7 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写7 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李7 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易7 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding7 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马7 小时前
前沿视界
前端
kyriewen8 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员