三、【vue3新手必看】深度解析 ref 和 reactive 的奥秘

ref和reactive是什么?

Vue3中的ref和reactive都是响应式的数据类型,它们都可以用来创建响应式的数据,

1、ref :创建基本类型的响应式数据

作用:定义响应式变量。
语法:const xxx = ref(初始值)

例如:const computerTemp = ref(35)

返回值:一个RefImpl的实例对象,简称ref对象refref对象的value属性是响应式的
<template>
  <div class="person">
    <h2>室内温度:{{ computerTemp }}</h2>
    <button @click="changecomputerTemp">修改室内温度</button>
  </div>
</template>
<script  setup name="HelloWorld">
import { ref } from 'vue'
let computerTemp = ref(35)
function changecomputerTemp() {
  computerTemp.value += 2
  console.log('computerTemp~~', computerTemp)
}
</script>

在这里插入图片描述

【注意】:
  • 在js中操作数据时需要:xxx.value,但模板中不需要.value,直接使用即可;
  • 对于const computerTemp = ref(35)来说,computerTemp 不是响应式的,computerTemp .value是响应式的。
  • 从控制台打印结果可以看出:computerTemp是一个RefImpl的实例对象,简称ref对象,它们的value属性是响应式的;
  • JS中操作ref对象时候必须要.value computerTemp.value是响应式的

2、ref :创建对象类型的响应式数据

  • ref接收的数据可以是:基本类型对象类型
  • ref接收的是对象类型,内部其实也是调用了reactive函数。
<template>
  <div class="person">
    <h2>个人信息:姓名{{ personInfo.name }},age{{ personInfo.age }}<button @click="changeAge">age+1</button></h2>
    <h2>作息表:</h2>
    <h3 v-for="item in table" :key="item.id">{{ item.name }}</h3>
    <button @click="changeName">click me</button>
  </div>
</template>

<script lang="ts" setup name="Person">
import { ref } from 'vue'
let personInfo = ref({ name: '菜鸟', age: 18 })
let table = ref([
  { id: '001', name: '吃早餐' },
  { id: '002', name: '吃午餐' },
  { id: '003', name: '吃晚餐' }
])
function changeAge() {
  personInfo.value.age += 10
  console.log('personInfo~~', personInfo)
}
function changeName() {
  table.value[0].name = '跑步'
  table.value[1].name = '午休'
  table.value[2].name = '学习'
  console.log('table~~', table);

}
</script>

在这里插入图片描述

3、reactive :创建对象类型的响应式数据

作用:定义一个响应式对象(基本类型不要用它,要用ref,否则报错)
语法:const 对象名= reactive({key:value…})

例如:const infoObj = reactive({ name: ‘菜鸟’, age: 18 })

返回值:一个Proxy的实例对象,简称:响应式对象。
<template>
  <div class="person">
    <h2>个人信息:</h2>
    <span>name:{{infoObj.name}}</span>
    <span>age:{{infoObj.age}}</span>
    <button @click="changeInfo">修改信息</button>
  </div>
</template>
<script  setup name="HelloWorld">
import { ref,reactive } from 'vue'
const infoObj = reactive({ name: '菜鸟', age: 18 })
function changeInfo() {
  infoObj.age += 1
  infoObj.name = 'cainiao'
  console.log('infoObj~~', infoObj)
}
</script>

在这里插入图片描述

【注意】:
  • reactive定义的响应式数据是“深层次”的;
let deepObj = reactive({
  a:{
    b:{
      c:{
        d:{
          x:666
        }
      }
    }
  }
})
function testDeep(){
  deepObj.a.b.c.d.x = 888
  console.log('deep~~',deepObj.a.b.c.d.x);
}

在这里插入图片描述

4、ref和reactive的区别

  • ref用来定义:基本类型数据对象类型数据
  • reactive用来定义:对象类型数据
  • ref创建的变量必须使用.value(可以使用volar插件自动添加.value)。
  • reactive重新分配一个新对象,会失去响应式(可以使用Object.assign去整体替换)。

【以下是reactive 使用不当会失去响应】

1、赋值一个普通对象

let state = reactive({ count: 0 })
// 这个赋值将导致 state 失去响应
state = { count: 1 }

2、赋值一个 reactive 对象

<template>
  {{ state }}
</template>    

<script setup>
const state = reactive({ count: 0 })
// 在 nextTick 异步方法中修改 state 的值
nextTick(() => {
  // 并不会触发修改 DOM ,说明失去响应了
  state = reactive({ count: 11 });
});
</script>

3、将 reactive 对象的属性赋值给变量(断开连接/深拷贝)
这种操作类似于深拷贝,不再共享同一内存地址,而是只是字面量的赋值,对该变量的赋值不会影响原来对象的属性值。

let state = reactive({ count: 0 })
// 赋值给 n,n 和 state.count 不再共享响应性连接
let n = state.count
// 不影响原始的 state
n++
console.log(state.count) // 0

4、直接 reactive 对象解构时

let state = reactive({ count: 0 })
// 普通解构,count 和 state.count 失去了响应性连接
let { count } = state
count++ // state.count 值依旧是 0

解决方法:

1、不要直接整个对象替换,一个个属性赋值

let state = reactive({ count: 0 })
state.count = 1

2、使用 Object.assign

let state = reactive({ count: 0 })
state = Object.assign(state, { count: 1 })

3、避免将 reactive 对象的属性赋值给变量。

4、使用 toRefs 解构,解构后的属性是 ref 的响应式变量。

const state = reactive({ count: 0 })
// 使用 toRefs 解构,后的属性为 ref 的响应式变量
let { count } = toRefs(state)
count.value++ // state.count 值改变为 1

5. 使用场景选择:

  • 对于简单数据类型,如数值、字符串等,必须使用ref。
  • 对于一个响应式对象,层级不深,refreactive都可以
  • 对于复杂对象类型,建议使用reactive。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值