在 Vue3 中 ref 和 reactive 都是用于创建响应式数据的,但它们有一些关键区别和使用场景。
ref
- 单一值: ref 用于创建一个响应式引用,通常用于基本类型(如 stringNumber,Boolean)
- 访问值: 当你需要访问 ref 创建的响应式变量时,需要使用 .value 属性
1 2
| const count = ref(0) console.log(count.value)
|
- 模板中的简化: 在模板中,你不需要使用 .value ,vue 会自动解引用
1 2 3 4
| <template> <div>{{ count }}</div> <!-- 自动解引用 --> </template>
|
- 可重新赋值: 你可以通过 count.value = 1 赋予一个新值。
- 转换对象: 使用 ref 创建的响应式对象,在解构或传递到其他函数时,会失去其响应性。需要使用 toRefs 或 toRef 来保持响应性。
- 保存 DOM 节点: 你可以通过 ref 将它与 DOM 元素绑定,从而在 JavaScript 中访问该 DOM 节点。这对操作 DOM、管理焦点等非常有用。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <template> <div ref="myDiv">Hello, Vue!</div> </template>
<script setup> import { ref, onMounted } from 'vue'
const myDiv = ref(null)
onMounted(() => { console.log(myDiv.value) // 输出 DOM 元素 }) </script>
|
这里的 myDiv 就是一个 ref,它指向了模板中的 div 元素,myDiv.value 可以访问到该 DOM 节点。
此外,ref 也能用来保存 非响应式的复杂对象,比如 DOM 节点、第三方库的实例等,这些场景中 ref 会更灵活。
reactive
- 对象/数组: reactive 用于创建响应式对象或数组
- 访问值: 访问 reactive 创建的响应式对象就像访问普通对象一样。
1 2
| const state = reactive({ count: 0 }) console.log(state.count)
|
- 不可重新赋值: 对 reactive 创建的响应式对象的根重新赋值(例如state = {}) 不会改变响应性。但其内部属性可以被修改。
- 嵌套响应性: 当你创建一个响应式对象,其内部嵌套的所有对象和数组也会自动变为响应式。
- 解构问题: 如果你解构一个使用 reactive 创建的响应式对象,解构出来的值将失去响应性。这与 ref 是相似的,但你可以使用 toRefs或 toRef 函数来解决这个问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { reactive, toRefs } from 'vue'
const state = reactive({ count: 0, name: 'Vue3', })
const { count, name } = state console.log(count)
const { count: reactiveCount, name: reactiveName } = toRefs(state) console.log(reactiveCount)
|
总结
- ref 适合创建单一/独立的值, 或者当你需要在模板中直接使用时
- reactive更适用于复杂的嵌套的 数组/对象 (vue3利用proxy对于嵌套的复杂数据有懒加载处理)
- 你可以使用 toRef 和 toRefs 这两个辅助函数 对 ref 和 reactive 进行转换
选择 ref 还是取决reactive于具体的需求和你的个人喜好,一些开发者更倾向于使用 ref 来管理所有状态(包括数组和对象),因为可以保持代码的一致性。
也可以根据用例来决定使用 ref 还是 reactive