Vue3中ref与reactive的用法详解——reactive

前言

在Vue2中的响应式数据需要放入 data 函数,Vue2 会遍历 data 中的所有属性,使用的Object.defineProperty 把每个 property 全部转为 getter/setter,getter 用来收集依赖,setter 用来执行 notify,发布更新事件。

而在Vue 3的响应式系统中使用了ref和reactive 这两个核心概念,它们为开发者提供了处理响应式数据的不同方式。理解它们的特性和区别对于构建灵活、高效的Vue应用至关重要

reactive

除了ref外,Vue3还有另一种声明响应式状态的方式,即使用 reactive() API。与将内部值包装在特殊对象中的ref不同,reactive() 将使对象本身具有响应性。

基本用法



相较于ref,reactive在Javascript中对数据修改时并不需要在.value属性下寻找,另外reactive的参数只能是对象或者数组或者像 Map、Set 这样的集合类型。

Proxy代理

const raw = {}
const proxy = reactive(raw)

// 代理对象和原始对象不是全等的
console.log(proxy === raw) // false

从以上代码可以看出,原始数据和reactive下的数据并不是全等的。因为reactive返回的是一个原始对象的Proxy。

// 在同一个对象上调用 reactive() 会返回相同的代理
console.log(reactive(raw) === proxy) // true

// 在一个代理上调用 reactive() 会返回它自己
console.log(reactive(proxy) === proxy) // true

为保证数据的一致性,代理对象调用reactive()仍会返回自己本身。

从以上代码的运行结果说明 reactive ()代理对象发生改变时,原始数据也会跟着发生变化。

注意事项

  • reactive 的参数只能是对象或者数组或者像 Map、Set 这样的集合类型。如果是原始数据类型,控制台会报警告
  • 由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失
let state = reactive({ count: 0 })

// 上面的 ({ count: 0 }) 引用将不再被追踪
// (响应性连接已丢失!)
state = reactive({ count: 1 })
  • 当我们将响应式对象的原始类型属性解构为本地变量时,或者将该属性传递给函数时,我们将丢失响应性连接
const state = reactive({ count: 0 })

// 当解构时,count 已经与 state.count 断开连接
let { count } = state
// 不会影响原始的 state
count++

// 该函数接收到的是一个普通的数字
// 并且无法追踪 state.count 的变化
// 我们必须传入整个对象以保持响应性
callSomeFunction(state.count)
  • 使用 reactive 定义的响应式对象,会深度监听每一层的属性,它会影响到所有嵌套的属性。即嵌套在响应式数据中的对象不论层级都会变成响应式对象。
  • 若要避免深层响应式转换,只想保留对这个对象顶层次访问的响应性,我们可以使用 shallowReactive()。

你可能感兴趣的:(vue.js,前端,javascript)