当前位置: 首页 > article >正文

《Vue进阶教程》第三十五课:自动脱ref

 往期内容:

《Vue进阶教程》第二十四课:优化

《Vue进阶教程》第二十五课:watch基本概念

《Vue进阶教程》第二十六课:实现侦听函数

《Vue进阶教程》第二十七课:实现侦听对象

《Vue进阶教程》第二十八课:实现新旧值

《Vue进阶教程》第二十九课:立即执行的回调

《Vue进阶教程》第三十课:watchEffect

《Vue进阶教程》第三十一课:ref的初步实现

《Vue进阶教程》第三十二课:ref响应丢失问题

《Vue进阶教程》第三十三课:toRef的使用

《Vue进阶教程》第三十四课:toRefs的使用

1) 什么是自动脱ref

所谓自动脱ref, 就是不写.value

对于ref类型数据, 每次在访问时, 需要加.value才能触发响应式.

但是这样做无疑增加了心智负担, 尤其是在写模板时, 不够优雅

为此, Vue3提供一个API: proxyRefs

对传入的ref类型对象进行代理, 返回proxy对象

个人理解: 有点类似toRefs的逆操作??

2) 基本使用

使用演示

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="./vue.js"></script>
  </head>
  <body>
    <script>
      const { ref, proxyRefs, effect } = Vue
      const count = ref(0)

    	// 1.模拟setup的返回对象
      // setup函数返回的对象会经过proxyRefs处理
      // 这样在模板中就不用写.value了
      const setup = proxyRefs({
        count,
      })

    	// 2.模拟页面渲染
      effect(() => {
        console.log('不用通过.value访问', setup.count)
      })
    </script>
  </body>
</html>

3) proxyRefs的实现

基本实现

function proxyRefs(objectWithRefs) {
  return new Proxy(objectWithRefs, {
    get(target, key, receiver) {
      // 使用Reflect读取target[key]
      const obj = Reflect.get(target, key, receiver)
      // 如果obj是ref类型, 返回obj.value; 否则, 直接返回
      return obj.__v_isRef ? obj.value : obj
    },
    set(target, key, newVal, receiver) {
      const obj = target[key]
      if (obj.__v_isRef) {
        obj.value = newVal
        return obj
      }
      return Reflect.set(target, key, newVal, receiver)
    },
  })
}

源码解读

源码对传入参数加强了判断

  1. 如果objectWithRefs已经是reactive类型, 就直接使用

源码按功能进一步细化, 可读性更高

  1. unref函数可以复用: 如果是ref返回.value; 否则直接返回
  2. 将proxy的handler提取成shallowUnwrapHandlers函数
  3. 在set时, 加入了新旧值类型的判断, 更严谨
function unref(ref) {
  return isRef(ref) ? ref.value : ref
}
const shallowUnwrapHandlers = {
  get: (target, key, receiver) => unref(Reflect.get(target, key, receiver)),
  set: (target, key, value, receiver) => {
    const oldValue = target[key]
    if (isRef(oldValue) && !isRef(value)) {
      oldValue.value = value
      return true
    } else {
      return Reflect.set(target, key, value, receiver)
    }
  },
}
function proxyRefs(objectWithRefs) {
  return isReactive(objectWithRefs)
    ? objectWithRefs
    : new Proxy(objectWithRefs, shallowUnwrapHandlers)
}


http://www.kler.cn/a/470141.html

相关文章:

  • 获取IP地区
  • stm32week3
  • 【开源工业视觉库】启航规划
  • jenkins入门9--参数化构建
  • 【MATLAB】【Simulink仿真】向模型中添加自定义子系统
  • 如何在 Spring Cloud Gateway 中创建全局过滤器、局部过滤器和自定义条件过滤器
  • C语言基础:指针(常量指针和指针常量)
  • js -音频变音(听不出说话的人是谁)
  • Flink系列知识讲解之:网络监控、指标与反压
  • 计算机的错误计算(二百零三)
  • 2025年最新 Tensorflow paddlepaddle与CUDA 、Python、cuDNN的版本对应表 一一对应关系,torch和CUDA的对应表
  • 科普CMOS传感器的工作原理及特点
  • windows C#-如何在派生类中引发基类事件
  • SPringMVC(2)——SpringMVC请求
  • 通过 oh-my-posh posh-git 优化PowerShell
  • 『SQLite』详解运算符
  • Lua语言的字符串处理
  • Node.js 中 http 模块的深度剖析与实战应用
  • 面试经典150题——链表(二)
  • ASP.NET Core 中服务生命周期详解:Scoped、Transient 和 Singleton 的业务场景分析
  • 汉诺塔..
  • React:构建现代 Web 应用的利器
  • 基于Node.js的水产品销售平台
  • linux 查看 MySQL 在 Linux 或 WSL 上的运行状态
  • WebSocket 测试调试:工具与实践
  • 哺乳动物各器官和物种中长链非编码RNA的发育动态