Vue 3 中 ref 和 reactive 的区别及原理

91 阅读2分钟

Vue 3 中 ref 和 reactive 的区别及原理

在 Vue 3 中,ref 和 reactive 是创建响应式数据的两种常用方式。很多开发者在使用过程中会对它们的区别和原理产生疑问,尤其是为什么 ref 需要用 .value 取值。今天我们就来深入探讨一下这个问题。

一、reactive 的原理和局限性

reactive 是 Vue 3 中用于创建响应式对象的函数,它的参数必须是一个对象,返回值是一个 Proxy 对象,具有响应性。例如:

import { reactive } from 'vue'
const state = reactive({ count0 })
console.log(state.count// 0

然而,reactive 有一些局限性。首先,它的参数只支持对象类型,不支持基本数据类型。其次,如果对变量重新赋值,会丢失响应性。例如:

let state = reactive({ count: 0 })
state = reactive({ count: 1 }) // 响应性丢失

此外,解构赋值也容易丢失响应性:

const state = reactive({ count: 0 })
let { count } = state
count++ // 不会影响 original state

在这种情况下,我们可以使用 toRefs 函数将响应式对象转换为 ref 对象,以保持响应性。

二、ref 的优势和原理

ref 是另一种创建响应式数据的方式,它的参数既可以是基本数据类型的值,也可以是对象。例如:

import { reffrom 'vue'
const name = ref('张三')
console.log(name.value// 张三

ref 的优势在于它支持基本数据类型,并且在取值时需要加上 .value。这使得 ref 在开发中更灵活,也更推荐使用。

从源码角度看,ref 的实现是通过 RefImpl 类,其中定义了 get 和 set 函数。当我们对 ref 的值进行取值和赋值时,会触发这两个函数。例如:

class RefImpl {
  get value () {
    console.log('get')
    return '111'
  }
  set value (val) {
    console.log('set')
  }
}

const refnew RefImpl()
ref.value = '123'
ref.value

这里,ref.value 的取值和赋值会分别触发 get 和 set 函数。这就是为什么 ref 需要用 .value 取值的原因。

三、ref 和 reactive 的关系

虽然 ref 和 reactive 都是用于创建响应式数据,但它们的实现方式有所不同。ref 的底层也用到了 reactive,只不过 ref 多包装了一层,支持了基本数据类型的值。例如:

this._value = __v_isShallow ? value : toReactive(value)

这里的 toReactive 函数会将对象类型的值转换为响应式对象,而 ref 则在此基础上支持了基本数据类型。

四、总结

在 Vue 3 中,ref 和 reactive 都是重要的响应式工具。ref 更加灵活,支持基本数据类型,而 reactive 则适用于对象类型的响应式数据。在开发中,我们更推荐使用 ref,因为它能更好地满足各种需求。

希望这篇文章能帮助你更好地理解 Vue 3 中 ref 和 reactive 的区别和原理。