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() 将使对象本身具有响应性。

基本用法

<template>
    <button @click="addCount">
      {
  { state.count }}
    </button>
</template>

<script setup>
import { reactive } from 'vue'

const state = reactive({ count: 0 })

const addCount = () => {
    state.count++
}
</script>

相较于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()仍会返回自己本身。

<script setup>
  import { reactive } from 'vue'

  const obj = {
    count: 1
  }
  const proxy = reactive(obj);
  
  proxy.count++;
  console.log(proxy.count); // 2
  console.log(obj.count);   // 2
</script>

从以上代码的运行结果说明 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 定义的响应式对象,会深度监听每一层的属性,它会影响到所有嵌套的属性。即嵌套在响应式数据中的对象不论层级都会变成响应式对象。
<script setup>
  import { reactive } from 'vue'

  let obj = reactive({
    name: 'Minato',
    a: {
      b: {
        c: 1
      }
    }
  })

  console.log("obj: ", obj) //obj: Proxy(Object){name:'Minato',a:{……}}
  console.log("obj.name: ", obj.name) //'Minato'
  console.log("obj.a: ", obj.a) //Proxy(Object){b:{……}}
  console.log("obj.a.b: ", obj.a.b) //Proxy(Object){c:{……}}
  console.log("obj.a.b.c: ",obj.a.b.c) //1
</script>
  • 若要避免深层响应式转换,只想保留对这个对象顶层次访问的响应性,我们可以使用 shallowReactive()。
<script setup>
  import { shallowReactive } from 'vue'

  let obj = shallowReactive({
    name: 'Echo',
    a: {
      b: {
        c: 1
      }
    }
  })

 console.log("obj: ", obj) //obj: {name:'Minato',a:{……}}
 console.log("obj.name: ", obj.name) //'Minato'
 console.log("obj.a: ", obj.a) //{b:{……}}
 console.log("obj.a.b: ", obj.a.b) //{c:{……}}
 console.log("obj.a.b.c: ",obj.a.b.c) //1
</script>

相关推荐

  1. Vue3refreactive用法详解——reactive

    2024-02-05 07:22:01       31 阅读
  2. Vue3reactiveref

    2024-02-05 07:22:01       20 阅读
  3. Vue3.0refreactive

    2024-02-05 07:22:01       17 阅读
  4. vue3reactiveref

    2024-02-05 07:22:01       8 阅读
  5. vue3reactiveref

    2024-02-05 07:22:01       9 阅读
  6. Vuerefreactive区别

    2024-02-05 07:22:01       41 阅读
  7. Vuerefreactive

    2024-02-05 07:22:01       17 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-05 07:22:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-05 07:22:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-05 07:22:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-05 07:22:01       20 阅读

热门阅读

  1. 在建站和小程序方面,公司如何提升客户的体验

    2024-02-05 07:22:01       32 阅读
  2. 微信小程序封装wx.request以及小程序登录

    2024-02-05 07:22:01       33 阅读
  3. 【微信小程序】微信小程序开发:从入门到精通

    2024-02-05 07:22:01       29 阅读
  4. 26种设计模式之单例模式

    2024-02-05 07:22:01       24 阅读
  5. 一知半解,临时解决ajax跨域请求

    2024-02-05 07:22:01       26 阅读
  6. 后端返回给前端的数据格式有哪些?

    2024-02-05 07:22:01       34 阅读
  7. C 检查小端存储还是大端

    2024-02-05 07:22:01       25 阅读
  8. appium抓包总结

    2024-02-05 07:22:01       35 阅读