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

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

 往期内容:

《Vue进阶教程》第二十二课:自定义更新(调度器)

《Vue进阶教程》第二十三课:渲染计算属性的结果

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

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

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

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

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

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

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

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

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

1) 基本使用
为了解决在赋值过程中响应丢失问题, Vue3提供了两个API
●toRef: 解决赋值问题
●toRefs: 解决展开, 解构问题
使用演示

toRef的使用

<!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="https://unpkg.com/vue@3.2.41/dist/vue.global.js"></script>
  </head>
  <body>
    <script>
      const { reactive, effect, toRef, toRefs } = Vue
      // obj是reactive创建的响应式数据(proxy代理对象)
      const obj = reactive({ foo: 1, bar: 2 })

      effect(() => {
        console.log('obj.foo具有响应性:', obj.foo)
      })

      // 使用toRef定义, 取代基本赋值操作 foo = obj.foo
      const foo = toRef(obj, 'foo')
      effect(() => {
        console.log('foo.value具有响应性:', foo.value)
      })
    </script>
  </body>
</html>

2) toRef的实现

基本实现

function toRef(obj, key) {
  const wrapper = {
    get value() {
      return obj[key]
    },
    set value(val) {
      obj[key] = val
    },
  }

  Object.defineProperty(wrapper, '__v_isRef', {
    value: true,
  })

  return wrapper
}

在Vue3中, 将wrapper抽象成了ObjectRefImpl类的实例, 大致的实现如下

reactive.js

class ObjectRefImpl {
  constructor(_obj, _key) {
    this._obj = _obj
    this._key = _key
    this.__v_isRef = true
  }
  get value() {
    return this._obj[this._key]
  }
  set value(newVal) {
    this._obj[this._key] = newVal
  }
}

function toRef(obj, key) {
  return new ObjectRefImpl(obj, key)
}

源码解读

  1. 源码中的toRef实现了默认值的功能
  2. 源码中的toRef对要转换的数据做了判断, 如果已经是ref类型就直接返回
class ObjectRefImpl {
  // 支持默认值
  constructor(_object, _key, _defaultValue) {
    this._object = _object
    this._key = _key
    this._defaultValue = _defaultValue
    this.__v_isRef = true
  }
  get value() {
    const val = this._object[this._key]
    return val === undefined ? this._defaultValue : val
  }
  set value(newVal) {
    this._object[this._key] = newVal
  }
}
// 1. 支持默认值
function toRef(object, key, defaultValue) {
  const val = object[key]
  // 2. 如果要转换的对象已经是ref类型, 直接返回
  //    eg: state = reactive({foo: ref(1)}) state.foo已经是ref类型, 直接返回ref(1)
  return isRef(val) ? val : new ObjectRefImpl(object, key, defaultValue)
}

测试用例

<!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="./reactive.js"></script>
  </head>
  <body>
    <script>
      // obj是响应式数据
      const obj = reactive({ foo: 1, bar: 2 })

      const foo = toRef(obj, 'foo')

      effect(() => {
        console.log('foo.value具备响应性:', foo.value)
      })
    </script>
  </body>
</html>


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

相关文章:

  • 个人交友系统|Java|SSM|JSP|
  • RK3588+FPGA全国产异步LED显示屏控制卡/屏幕拼接解决方案
  • 普及组集训数据结构--并查集
  • Kafka3.x KRaft 模式 (没有zookeeper) 常用命令
  • “AI智慧教学系统:开启个性化教育新时代
  • SpringCloud源码分析-nacos与eureka
  • 【TensorFlow】tensorflow简介和环境搭建、入门
  • 掌握 Stream API - Java 8 的力量
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之12 方案再探之3:特定于领域的模板 之2 首次尝试和遗留问题解决
  • 异常与中断(上)
  • C++设计模式:状态模式(自动售货机)
  • HIVE函数使用案例之----行列转换
  • nginx学习之路-nginx配置https服务器
  • 17爬虫:关于DrissionPage相关内容的学习01
  • 大模型—Ollama将Python函数作为参数传递,增强函数调用功能
  • shell脚本的【算数运算、分支结构、test表达式】
  • PHP:IntelliJ IDEA 配置 PHP 开发环境及导入PHP项目
  • OpenCV 特征检测和特征匹配方法汇总
  • 如何使用大语言模型进行事件抽取与关系抽取
  • smolagents:一个用于构建代理的简单库
  • SpringBoot教程(三十二) SpringBoot集成Skywalking链路跟踪
  • hhdb客户端介绍(65)
  • HT-HaiBOX边缘计算盒 智慧工厂方案,智慧医疗方案,智慧加油站方案,智慧安防方案,智慧城市方案;方案定制开发
  • Python编程实现“天天酷跑”小游戏(源码附上)
  • 基于单片机的野营自动感应灯系统(论文+源码)
  • 使用Wikitext2数据集对Llama-7B和Llama3-8B模型进行50%权重剪枝的一般步骤和可能的实现方式