[深入vue3之refs] ref、unref、toRef、toRefs、isRef、customRef、shallowRef、triggerRef等使用与讲解

44 篇文章 6 订阅

本章涉及的composition api:

ref、unref、toRef、toRefs、isRef、customRef、shallowRef、triggerRef

refs api中的重点为:ref、toRefs、shallowRef、customRef,其次是 isRef 等。


  • ref
  1. 接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象仅有一个 `.value` property,指向该内部值。

  2. 如果将对象分配为 ref 值,则它将被 `reactive` 函数处理为深层的响应式对象。

  3. template 内使用 ref 对象,会自动解包。

<template>
  <div>
    {{Redf}}
  </div>
</template>
<script lang='ts' setup>
import { ref,isReactive } from 'vue';
let Redf = ref('南中乱党')
console.log(Redf.value);

let objData = ref({})
console.log(isReactive(objData.value));
</script>

  • unref
  1. 如果参数是一个 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 的语法糖函数。

  2. 基于 ref 一个 {} , {} 会被 reactive 二次处理,unref(ref({})) 返回的是响应式的 {}

<script lang='ts' setup>
import { ref } from 'vue';
let Redf = ref('南中乱党')
let un1 = unref({})
let un2 = unref(Redf)
let un3 = unref(ref({})) // un3 > proxy {}
</script>

  • toRef
  1. 参数: `(源对象 , 源对象属性)`

  2. 可以用来为源响应式对象上的某个 property 新创建一个 ref。然后,ref 可以被传递,它会保持对其源 property 的响应式连接。

  3. 用人话讲就是为 源响应式对象(toRef的第一个参数) 上的某个 property 新创建一个 ref  

<script lang='ts' setup>
import { reactive,toRef } from 'vue';
//! 新的ref对象对源property建立响应式连接,修改其中一个,另一个也会同步!
const state = reactive({
  foo: 1,
  bar: 2
})
const fooRef = toRef(state, 'foo')
fooRef.value++
state.foo++
console.log(fooRef,state) // 3
</script>

  • toRefs
  1. 将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref。

  2. 主要功能:当从组合式函数 (.js) 返回响应式对象时,用toRefs就可以在不丢失响应性的情况下对返回的对象进行解构/展开。  

  3. toRef 是转单个, toRefs全转。

原理:toRefs 会将 reactive 生成的对象的根级属性全都用 ref 转成 ref 对象,然后解构出来的都是 ref 对象,从而不丢失响应式

<script lang='ts' setup>
import { reactive,toRef } from 'vue';
const state = reactive({
  foo: 1,
  bar: 2
})
let a = {...state}
const stateAsRefs = toRefs(state)
// stateAsRefs 是一个普通对象,stateAsRefs.foo则是响应式对象,因此{...}解构才不会丢失响应式
let {bar} = stateAsRefs 
console.log(stateAsRefs)
console.log(stateAsRefs.foo.value) // 因为使用了 ref ,理所应当 .value。
console.log(a)
</script>

  • isRef
  1. 检查值是否为一个 ref 对象。

<script lang='ts' setup>
import { isRef } from 'vue';
// ()内例子是上面的。
console.log(isRef(Redf));
console.log(isRef(stateAsRefs.foo));
</script>

  • customRef
  1. 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track 和 trigger 函数作为参数,并且应该返回一个带有 get 和 set 的对象。  

自定义 ref 的get set,用于某些数据变更操作的额外功能封装,可以理解为computed 指令类似的功能之类的

<script lang='ts' setup>
import { useDebouncedRef } from 'vue';
function useDebouncedRef(value, delay = 200) {
  let timeout;
  return customRef((track, trigger) => {
    return {
      get() {
        return value
      },
      set(newValue) {
        // 此处可以做一系列操作进行数据处理。
        // 例子1:使用自定义 ref 通过 v-model 实现 debounce 的示例:
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()
        }, delay)
      }
    }
  })
}
let a23 = useDebouncedRef('hello')
</script>

  • shallowRef
  1. 如字面意思,浅响应式,如果传入的是基本类型跟 ref 没区别。

  2. 如果传入的是引用类型,.value值将不会是响应式的数据,ref的 value 属性则会是响应式的。

<script lang='ts' setup>
import { shallowRef,isReactive } from 'vue';
const foo = shallowRef({a:1})
// 改变 ref 的值是响应式的
foo.value = {b:2}
// 但是这个值不会被转换。
isReactive(foo.value) // false
</script>

备注: <script setup>语法糖时,动态组件最好就是用 shallowRef


  • triggerRef
  1. 手动执行与 shallowRef 关联的任何作用 (effect)。

  2. 简单讲就是配合 shallowRef 用的,并且 shallowRef 传入的是个引用类型。

<script lang='ts' setup>
import { shallowRef,watchEffect,triggerRef } from 'vue';
const shallow = shallowRef({
  greet: 'Hello, world'
})
watchEffect(() => {
  // 第一次运行时记录一次 "Hello, world"
  console.log(shallow.value.greet)
})
shallow.value.greet = 'Hello, universe'

// 首先 watchEffect 追踪的是响应式数据,shallowRef 是浅层的,  
// 所以当是{}的时候,无法触发 effect ,每次操作 shallow.value 的时候,则需要 triggerRef(shallow) 主动触发执行。  
// 记住,是每次操作,都需要 triggerRef() 一下
triggerRef(shallow)
</script>


QQ交流群:522976012  ,欢迎来玩。

聚焦vue3,但不限于vue,任何前端问题,究其本质,值得讨论,研究与学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值