Vue3 如何理解 ref toRef toRefs

如何理解 ref toRef toRefs

细节的知识点,在整个 Composition API 中算是比较难理解的。

ref 和 reactive 结合起来使用,更是难以理解。 既然有 reactive ,为何还要 ref 呢

refs-api

ref

( 创建响应式对象一般用 reactive )

用法 :

  • 第一,响应式 (代码参考 RefBasic.vue

    • 生成值类型的响应式数据

    • 可直接用于模板和 reactive中 ( 不需要 .value )

    • 可通过 .value 修改值

  • 第二,模板引用 -> 获取dom元素(代码参考 RefTemplate.vue

toRef

可以用来为源响应式对象上的 property 新创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。

  • 针对一个响应式对象 ( reactive 封装 )的 property

  • 创建一个 ref 具有响应式

  • 两者保持引用关系

【注意】必须是响应式对象,普通对象不具有响应式。

toRefs

代码参考 ToRefs.vue

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

  • 响应式对象 ( reactive 封装 )转换为普通对象 obj

  • 对象的每个属性都是对应的 ref

  • 保持引用关系

【注意】必须是响应式对象,普通对象不具有响应式。

当从合成函数返回响应式对象时,toRefs 非常有用。

( 直接使用 ...解构响应式对象会使得其丢失响应性)

这样消费组件就可以在不丢失响应性的情况下对返回的对象进行分解/扩散

 function useFeatureX() {
   const state = reactive({
     x: 1,
     y: 2
   })
   // 逻辑运行状态,省略 N 行
 ​
   // 返回时转换为ref
   return toRefs(state)
 }
 ​
 export default {
   setup() {
     // 可以在不失去响应性的情况下破坏结构
     const { x, y } = useFeatureX()
 ​
     return {
       x,
       y
     }
   }
 }

ref 和 reactive

既然有 reactive ,为何还要 ref 呢?

  • 返回值类型,会丢失响应式

  • 如在 setup、computed、合成函数,都有可能返回值类型

  • Vue 如不定义 ref ,用户将自造 ref ,反而混乱

代码参考 ref/WhyRef.vue

为何需要 .value

  • 因为要保证响应式,需要把值类型封装成一个对象形式,所以用 .value 表示这个值

  • 通过 .value 属性的 get 和 set 实现响应式

  • 模板中 和 reactive 使用时,不需要 .value

  • 其他情况都需要 .value

结合 computed 的内部实现,可如下解释:

 // 伪代码:不具有响应式,即改变值不会触发渲染
 function computed(getter) {
   let value
   watchEffect(() => {
     value = getter() // value 是值类型,值拷贝,value 的变化不会传递到下游
   })
   return value
 }
 ​
 // 伪代码:具有响应式
 function computed(getter) {
   const ref = {
     value: null,
   }
   watchEffect(() => {
     ref.value = getter() // ref 是引用类型,指针拷贝,ref 的变化会传递到下游
   })
   return ref
 }

上述代码,可以把 watchEffect 改为 setTimeout 模拟一下

再聊 toRef 和 toRefs

  • 设计初衷:不丢失响应性的情况下对返回的对象进行分解/扩散

  • 必须存在:因为直接 property 或者 ...state ,会直接拿到属性的值。如果属性是值类型,则会丢失响应式 !!!(响应式是 Proxy 实现的)

  • 注意事项:不创造响应式,而是延续响应式 (所以针对普通对象不行,必须是响应式对象)

toRef toRefs 必须针对一个响应式对象,普通对象是无法变成响应式的。 它俩的设计初衷,本来也是针对响应式对象的 组合式 API 常见问答 | Vue.js 即,想要实现响应式,只有两个方法:ref reactive

  • ref 创造响应式

  • toReftoRefs 延续响应式

为何必须使用 toRef(state, 'name')toRefs(state) ??? 因为直接 property 或者 ...state ,会直接拿到属性的值。如果属性是值类型,则会丢失响应式。(响应式是 Proxy 实现的) 这也是引入 ref 的根源!!! 也是引入 Composition API ,抛弃 this ,带来的结果。

从使用角度

理解和应用要分开总结,这很重要。即便你听不懂原理,也要知道如何使用。

  • ref 值类型响应式

  • ref 模板引用

  • setup 返回时用 toRefs(state)

  • 用于第三方的逻辑函数,如 demo 中的 useMousePosition

  • 为所有的 ref 名加类似 xxxRef 的后缀


ref 和 reactive 混合起来,真的非常乱。 相比之下,React Hooks 只有 useState ,反而简单很多。—— 当然它也有其他的一些理解成本。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值