Vue3之ref和reactive的使用与区别

   ref() 和 reactive() 都是响应式api,用来跟踪其参数的更改,让组件具有响应性。

1. ref和reactive的区别

1.1 接收值不同

ref

        ref 可以处理基础类型的值,也可以处理引用类型的值

        如果给 ref 函数传递了一个引用类型的值,如传递一个对象,那么这个对象就会通过 reactive() 这个方法将其转换成具有深层次的响应式对象,也就是说这种情况下ref 内部本质还是调用了 reactive 方法。

const ref1 = ref(0)            // OK
const ref2 = ref({ count: 0 }) // OK

reactive        

        reactive 仅处理引用类型的值,不允许传递基础类型的值。

        reactive若传入基础类型的值,对该基础类型数据是没有响应式追踪能力的。

const reactive1 = reactive(0)            // NOT OK
const reactive2 = reactive({ count: 0 }) // OK

1.2. 数据访问方式不同

ref

        对于 ref 来说,无论是原始类型还是对象,访问数据都需要通过 .value 的形式进行,更新数据也需要通过 .value 来更新。

        但在<template>中使用ref的值时不需要带上.value。

const ref1 = ref(0) 
console.log(ref1.value)  // 0

const ref2 = ref({ count: 0 })
console.log(ref2.value.count)  // 0

ref1.value = 1
console.log(ref1.value)  // 1
<template>
      <div>{{ ref1 }}</div>
</template>

<script setup>
    import { ref } from 'vue'
    const ref1 = ref(0)
</script>

reactive        

        reactive是 proxy 代理的对象数据,可以直接获取到数据,不必添加 .value。

        看到ref取值和reactive的取值方式不同,可以看出ref本质就是基于reactive的二次包装。

const reactive1 = reactive({ num: 0}) 
console.log(reactive1.num)  // 0

1.3. watch监听方式不同

ref

        可以直接监听 ref 的数据,当 ref 的数据发生变化的时候,就会执行 watch 函数对应的回调。

const ref1 = ref(0)
watch(ref1, () => { 
  console.log('changed!')
})

        当然这里只是原始类型数据,如果是对象的话,需要深度监听 deep: true

const ref1 = ref({num: 1})
watch(ref1, () => { 
    console.log('changed!')
})

// ref1.value.num = 1 
// 执行该语句时并不会触发watch监听,watch 并没有对ref1进行深度监听
// 但注意,此时dom是能更新的,ref会将其转换成 reactive 的形式

// 要想深入监听,只需要加一个对应的参数即可
const ref1 = ref({num: 1})
watch(ref1, () => { 
    console.log('changed!')
}, { deep: true })

reactive

        reactive 因为本质是对象,所以在 watch 的时候本能的会添加 deep 属性。

        vue 对其做了优化watch 监听 reactive 的时候可以不添加 deep 属也能够对其做深度监听。

const reactive1 = reactive({num: 1})
watch(reactive1, () => { 
    console.log('changed!')
})

// reactive1.num = 1
// 触发watch监听

备注

        对比 ref,reactive 会跟踪每个属性的变动。
        这意味着在 reactive 中的每个属性都会被视为独立的 ref ,Vue 会据此确定是否需要更新某些依赖于这些属性的内容
        如果想使用ref 作为状态容器,那么每当一个属性更新时,使用该状态的任何地方都将被更新。这会触发不必要的重新渲染并减慢应用程序的速度。

2. ref、toRef、toRefs的区别

ref

        复制,修改响应式数据不影响以前的数据。

toRef

        引用,修改响应式数据会影响以前的数据。

toRefs

        1. 接收一个对象作为参数,它会遍历对象身上所有属性,然后调用单个toRef。

        2. 将对象的多个属性变成响应式数据,并且要求响应式数据和原始数据关联。

3. 通过typeof判断ref和reactive类型

3.1. ref 类型判断   

        ref 关键字声明一个变量时,变量的类型会被推断为 Ref 类型,无论变量本身是什么类型的值,typeof 判断为Object。
        可以使用 unref 函数来解包得到ref 对象的实际值,再对unref()进行判断。

let num = ref(123)
console.log(typeof num) //Object
console.log(typeof unref(num)) //Number

3.2.reactive类型判断 

        reactive用来声明复杂数据类型时,typeof判断为Object。

let myName = reactive({name:'min'})
console.log(typeof myName) //Object
console.log(typeof myName.name) //String

疑惑

        reactive用来声明基础数据类型时,typeof判断按理说会判断为Object(被reactive包装了)

        但试验发现仍会判断为原本的数据类型

        但总而言之是不推荐用reactive包裹基础数据类型的

let obj = reactive(123)
console.log(typeof obj) //number

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值