ref函数与reactive函数的一些小细节

解包

通过ref函数转化后,会返回一个 RefImpl 引用对象。在js中使用该变量时,我们需要通过 xxx.value 来进行操作。但是当我们在模板中通过插值语法来使用xxx变量时,Vue3 会自动解包,找到 xxx.value ,而我们在模版上只需要按照正常插值语法书写即可

<template>
  <p>工作:{{ name }}</p>
  <button @click="changeName">点击修改</button>
</template>

let name = ref('al')

function changeName() {
  name.value = '汤圆仔'
}

而经过 reactive 函数转化的普通对象中,因为返回的是 Proxy 代理对象,所以不需要解包这一操作,就和普通对象一样操作即可

  <p>工作:{{ userInfo.name }}</p>
  <button @click="change">点击修改</button>

  let userInfo = reactive({
    name:'al'
  });

  function change() {
    userInfo.name = 999
  }

如果 reactive 函数接收的是一个 通过ref函数转化的响应式对象,那么这个经过ref转化的响应式数据在作为 reactive 函数再次转化之后的响应式数据在被访问或被修改时,也会像一个普通属性一样,完成自动解包的操作

let userInfo = ref({name:'al'});    //这里返回的是一个 RefImpl 引用对象

const state = reactive({
  userInfo    //这里的userInfo 就是上面的 RefImpl 引用对象
})

console.log(state)    //返回的是Proxy对象 Proxy(Object){userInfo:RefImpl}

console.log(state.userInfo.name) // al 当通过 reactive 返回的 Proxy 实例访问name属性时,会自动解包 其实访问的是 state.userInfo.name.value

state.userInfo.name = '汤圆仔'    // 同理,修改name值时,也是自动解包,修改的是state.userInfo.name.value = '汤圆仔’

console.log(userInfo.value.name) // 汤圆仔    而且因为 ref是响应式,reactive 也是响应式,所以修改 reactive 对象的数据后其实也同步到了 ref 对象上

如果 reactive 函数接受得是一个标准的数组,那我们在操作数组的时候,也是像操作普通数组一样,通过数组下标进行操作,不用解包

const hobby = reactive(['吃饭'])    // 传入标准数组格式

console.log(hobby,'hobby');    // 返回的是一个 Proxy 代理对象 Proxy(Array){0:'吃饭'}

如果 reactive 函数接收的是一个经过ref函数转化过的 数组,那么我们在操作数组的时候,又需要加上 value了,这里就和 上面的 reactive 函数 接收一个 通过ref转化标准对象形式的结果形成了对比

const books = reactive([ref('学习')])    

console.log(books,'books')    // 返回 Proxy 代理对象 Proxy(Array){0:RefImpl}

console.log(books[0],'books[0]')    //直接返回 RefImpl 引用对象

console.log(books[0].value,'books[0].value')    //到了这一步,才能真正取到数组第一个值

同理,如果reactive 函数接收的是一个 原生集合类型 (如 Map

const work = reactive(new Map([['前端', ref('学习')]]))  
 
console.log(work, 'work');    // 返回 Proxy 代理对象 Proxy(Map){'前端' => RefImpl}

console.log(work.get('前端'), 'work.get');    // 得到 Proxy 代理对象 Proxy(RefImpl)

console.log(work.get('前端').value, 'work.get.value');    // 得到 键 对应的值 学习

在模板中,只有顶级属性才会被解包,例如下面的 count和object都是顶级属性,但是 object.id则不是顶级属性

let count = ref(0)

let object = { id: ref(1) }

所以在模板插值表达式中,

  <p>{{ count + 1 }}</p>    //  渲染正确count 会自动解包 最终展示为 2

  <p>{{ object.id + 1 }}</p>    // 渲染错误 最终展示为 [object Object]1 字符串。因为 object是一个对象{id:refImpl} ,object.id 则是一个 RefImpl 引用对象,使用object.id 时,因为 object.id bus不是顶层属性,所以不会自动解包,需要使用 value 属性获取真正的值

为了解决这个问题,我们可以将 object 进行解构,使得object.id 成为顶层属性,从而实现自动解包

let object = { id: ref(1) }

let {id} = object    //通过解构实现,将id变成顶级属性,从而自动解包

<p>{{ id + 1 }}</p>    // 展示正确 最终渲染结果为2

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以用中文回答你的问题。 在Vue 3中,`ref`和`reactive`都是用于在Vue组件中创建响应式数据的函数。 `ref`函数接受一个参数,并返回一个响应式的对象。这个参数可以是任何JavaScript类型,包括对象、数组、字符串、数字等等。`ref`函数返回的响应式对象包装了传入的参数,使得该参数的任何变化都会被Vue自动检测到并触发重新渲染视图。要访问`ref`对象的值,需要使用`.value`属性。 例如: ``` import { ref } from 'vue' const count = ref(0) console.log(count.value) // 输出0 count.value++ // 修改count的值 console.log(count.value) // 输出1 ``` `reactive`函数也接受一个参数,但这个参数必须是一个普通的JavaScript对象。`reactive`函数会递归地将这个对象的所有属性转换成响应式的对象,从而实现响应式数据的功能。要访问`reactive`对象的值,可以直接使用对象属性访问方式。 例如: ``` import { reactive } from 'vue' const state = reactive({ count: 0 }) console.log(state.count) // 输出0 state.count++ // 修改state对象中count属性的值 console.log(state.count) // 输出1 ``` 总的来说,`ref`和`reactive`都是Vue 3中非常有用的响应式数据函数,用于实现组件中的数据绑定和响应式渲染。如果你只需要创建单一的响应式值,使用`ref`更为简单;如果你需要创建一个包含多个属性的响应式对象,使用`reactive`更为方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值