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

Vue3 —— to 全家桶及源码学习

  • 该文章是在学习 小满vue3 课程的随堂记录
  • 示例均采用 <script setup>,且包含 typescript 的基础用法

前言

本篇主要学习几个 api 及相关源码:

  • toRef
  • toRefs
  • toRaw

一、toRef

  • toRef(reactiveObj, key)
    • 接收两个参数,第一个是 响应式对象,第二个是 指定的key
    • 作用:将 响应式对象一部分也变为响应式,通过 .value 修改
  • toRef 对 非响应式 对象无能为力,修改后 视图不会更新
  • 直接解构 reactiveObj,不使用 toRef,会使解构出的值 丧失响应式
  • 应用场景:某个单独的 属性key 需要被单独使用,并 希望它是响应式的

① 对非响应式对象无能为力

<div class="">hobby:{{ hobby }}</div>
<button @click="change">修改</button>
//  普通对象
const man = {name: "xiaoman",age: 18,hobby: "ball",
};
const hobby = toRef(man, "hobby"); // 对普通对象使用,修改后仅修改值 但不更新视图const change = () => {hobby.value = "sing";console.log("hobby", hobby); // Ref<"sing">,但视图不更新
};

打印更新:
在这里插入图片描述

视图不更新:

在这里插入图片描述

② 将响应式对象的一部分也变为响应式

<div class="">hobby2:{{ hobby2 }}</div>
<button @click="change">修改</button>
// reactive 响应式对象
const man2 = reactive({name: "xiaoman",age: 18,hobby: "ball",
});
const hobby2 = toRef(man2, "hobby");const change = () => {hobby2.value = "dance";console.log("hobby2", hobby2, man2) // hobby2 和 man2 都会更新,视图也会更新
};

打印:

在这里插入图片描述

视图更新:

在这里插入图片描述

③ 直接解构响应式对象

直接解构 响应式对象,不使用 toRef,会使解构出的值 丧失响应式

// reactive 响应式对象
const man2 = reactive({name: "xiaoman",age: 18,hobby: "ball",
});
const { age } = man2; // 直接解构会丧失响应式
console.log("直接解构 age------", age);

解构出的就只是一个普通的值:

在这里插入图片描述

二、toRefs

  • toRefs(reactiveObj)
    • 和 toRef 作用一样,只是不再指定某个key,而是把全部属性都变为响应式
    • 也是需要 传入响应式对象,之后若对其解构,解构出的也是响应式对象
  • 外层不再是响应式,内部的每一个key才是响应式

① 简单实现 toRefs 的源码

其实就是定义一个循环,循环体中 调用 toRef

const toRefsCopy = <T extends object>(obj: T) => {const map: any = {};for (let key in obj) {map[key] = toRef(obj[key]);}return map;
};

② toRefs 使用

<div>refs:{{ refs }}</div>
<div>refs2:{{ refs2 }}</div>
<button @click="change2">修改</button>
const blue = reactive({name: "blue",age: 19,
});const refs = toRefsCopy(blue);
const refs2 = toRefs(blue);
console.log("refs---", refs, refs2);const change2 = () => {// 解构出的每一个key都是响应式const { age } = refs2;age.value = 24;console.log("toRefs", refs, age);
};

toRefs 和 toRefsCopy 处理过后,每个key都是响应式:

在这里插入图片描述
直接解构出的 key 也是响应式,会立刻更新:

在这里插入图片描述

三、toRaw

  • toRaw(reactiveObj)
    • 同样接收一个 响应式对象
    • 作用:toRaw 使 响应式对象 变为 普通原始对象
  • 取出 响应式对象__v_raw 对应的值,跟 toRaw 之后的结果相同(__v_raw 是源码内部的操作)
const people = reactive({name: "bill",age: 12,
});// 打印结果:people 是具有响应式的对象,toRaw 后就变成了普通原始对象
console.log("toRaw-------", people, toRaw(people));// 取出 __v_raw 对应的值,跟 toRaw 的结果相同
console.log("__v_raw-------", people["__v_raw"]);

在这里插入图片描述

四、源码学习

源码贴图:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源码理解记录:

/***(reactivity.cjs.prod.js)搜索 function toRef 即可找到** 1、function toRef (source, key, defaultValue)*    - 先判断 isRef,true的话直接返回*    - 再判断是不是函数类型,GetterRefImpl 内部仍然是直接返回,但会增加一些必要的标记(__v_isRef、__v_isReadonly)**    - 再判断是不是object,是的话走进 propertyToRef*        - 看 source[key] 是否满足 isRef,*            true的话直接返回(已经设置过响应式了)*            否则走进 ObjectRefImpl,这就是 toRef 的核心方法*        - ObjectRefImpl 与 RefImpl(ref) 内部同样有 get、set方法,*          但是区别在于 ObjectRefImpl 没有收集依赖(track)、触发更新(trigger) 的操作*          所以 toRef 对普通对象来讲没有响应式,只对已经有响应式的对象有用**    - 上述类型都不属于的话,直接 ref(source)**** 2、function toRefs (object)**    - 和上面自己写的 toRefsCopy 思路基本一致*        - 先初始化一下,[]或者{}*        - 然后循环,*                判断每个值 若 isRef=true 直接返回*                否则都 走进 ObjectRefImpl 中变为 ref 类型*** 3、function toRaw(observed)**    - 判断 observed 是否存在 __v_raw ,存在的话继续递归 toRaw,否则直接返回 observed*    - 取出的结果就是 不带 __v_raw 的原始普通对象***/
http://www.lryc.cn/news/117984.html

相关文章:

  • (第三篇) ansible-kubeadm在线安装高可以用集群()
  • flutter开发实战-颜色Color与16进制转换
  • Linux(进程地址空间)
  • VLAN监控及常见问题排查
  • PromQL实现Actuator获取的JVM指标的Full GC次数监控
  • 3.正则表达式
  • 【学习FreeRTOS】第3章——FreeRTOS移植及配置文件
  • Java算法_ LRU 缓存(LeetCode_Hot100)
  • Hugging Face 的文本生成和大语言模型的开源生态
  • Docker Compose用法详解
  • 分布式链路追踪概述
  • css中的var函数
  • 第五次作业 运维高级 构建 LVS-DR 集群和配置nginx负载均衡
  • neo4j电影库-关系查询
  • 2020/10-2023/7 Notes
  • 在UOS系统中管理ORACLE数据库
  • 以http_proxy和ajp_proxy方式整合apache和tomcat(动静分离)
  • 【pinia】Pinia入门和基本使用:
  • Linux 文件系统(一)系统目录
  • 『CV学习笔记』Opencv和PIL Image以及base64编码互相转化
  • 行业追踪,2023-08-07
  • CSRF 攻击和 XSS 攻击分别代表什么?如何防范?
  • RabbitMQ: 详解、使用教程和示例
  • redis NOAUTH Authentication required 可能不是密码问题
  • 动态规划解0-1背包问题(超详细理解)
  • 有哪些可能引起前端安全的问题?
  • 【Unity实战100例】用户头像圆形遮罩使用Shader不用Mask组件
  • arm-linux-gnueabihf-g++ gcc编译、优化命令 汇总
  • vmwera中安装的centos8出现ifconfig不可用
  • 线性表中的时间复杂度