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

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

前言

本章 ref 全家桶 主要包括以下几个api 和 对应源码的学习:

  • ref
  • isRef
  • shallowRef
  • triggerRef
  • customRef

一、api 各自的使用

1、ref

  • 使用 vue3 定义响应式数据 主要通过 refreactive
  • ref 可定义 任何类型数据,reactive 用来定义对象类型
  • ref 定义的数据,修改时要通过 .value,template 中使用时不需要 .value
  • ref 也可以用来 获取dom:dom上绑定 ref 属性,并用 ref 创建同名的响应式变量

① 基本使用

<div>{{ name }}</div>
import { ref, Ref } from "vue"const name: Ref<string> = ref('xiaoman');
name.value = 'blue'

② 获取dom

<div ref="dom">我是dom</div>
<button @click="getDom">获取dom</button>
import { ref } from "vue"
const dom = ref<HTMLElement>();
function getDom() {// ?.的形式,先判断再获取console.log(dom.value?.innerText);
}

在这里插入图片描述

2、isRef

字如其意,就是 判断一个变量是不是 ref 类型的响应式数据,返回布尔值

import { ref, Ref, isRef } from "vue"const name: Ref<string> = ref('xiaoman');
name.value = 'blue'console.log(isRef(name)); // true

3、shallowRef

  • ref 深层 的响应式 ,shallowRef浅层 的响应式
  • 深层 的响应式:不管怎么修改都会 直接触发视图更新
  • 浅层 的响应式:修改 深层数据 时,数据修改成功,但 不会立刻更新视图
  • 若同时修改 ref 和 shallowRef 的数据,shallowRef 的视图会被顺带更新,所以不要同时使用!

① 该例子中,ref 被修改后,会立刻触发视图的更新

<div>Man:{{ Man }}</div>
<button @click="changeMan">改变ref</button>
import { ref, Ref } from "vue"// 使用 type 定义类型
type M = {name: string;
};
const Man: Ref<M> = ref({ name: "小满" });function changeMan() {Man.value.name = "大满1";
}

② 该例子中,shallowRef 被修改后,数据打印显示更新,但不会更新视图

<div>Man2:{{ Man2 }}</div>
<button @click="changeMan">改变ref</button>
import { shallowRef, ShallowRef } from "vue"// 使用 type 定义类型
type M = {name: string;
};
const Man2: ShallowRef<M> = shallowRef({ name: "小满" });function changeMan() {Man2.value.name = "大满2";// 这里打印更新,但是不更新视图console.log("Man2.value.name", Man2.value.name); 
}

控制台打印数据已更新:

在这里插入图片描述

但视图未更新:
在这里插入图片描述

③ 若将 ref 和 shallowRef 同时更新,shallowRef 的视图也会被顺带更新

<div>Man:{{ Man }}</div>
<div>Man2:{{ Man2 }}</div>
<button @click="changeMan">改变ref</button>
import { ref, Ref, shallowRef, ShallowRef } from "vue"// 使用 type 定义类型
type M = {name: string;
};
const Man: Ref<M> = ref({ name: "小满" });
const Man2: ShallowRef<M> = shallowRef({ name: "小满" });function changeMan() {Man.value.name = "大满1";Man2.value.name = "大满2";
}

视图全部更新:

在这里插入图片描述

4、triggerRef

  • 作用:强制触发视图的更新
  • ref 在源码中 会调用 triggerRef 进行视图的 强制更新,这也就是 ref 和 shallowRef 混用时 shallowRef 视图也会被更新的原因

我们使用 shallowRef + triggerRef 看看效果:

<div>Man2:{{ Man2 }}</div>
<button @click="changeMan">改变ref</button>
import { shallowRef, ShallowRef, triggerRef } from "vue"// 使用 type 定义类型
type M = {name: string;
};
const Man2: ShallowRef<M> = shallowRef({ name: "小满" });function changeMan() {Man2.value.name = "大满2";triggerRef(Man2);
}

果然,视图更新:

在这里插入图片描述

5、customRef

  • 作用:用来 自定义 ref
  • 接收一个函数
    • 函数有 两个参数track 收集变化trigger 触发更新
    • 函数 返回一个对象,里面自定义 getset 函数。get 中先收集变化再返回值set 中先设置新值再触发更新

① 先来写一个自定义ref

<div>custom:{{ custom }}</div>
<button @click="change">改变customRef</button>
import { customRef } from "vue"function MyRef<T>(value: T) {return customRef((track, trigger) => {return {get() {track();return value;},set(newVal) {value = newVal;console.log("触发set");trigger();},};});
}const custom = MyRef<string>("xiaoman");
function change() {custom.value = "daman";
}

点击后视图会立刻更新:

在这里插入图片描述

② 考虑到快速点击的场景,给 MyRef 函数做一下防抖

function MyRef<T>(value: T, delay = 500) {let timer: any = null;return customRef((track, trigger) => {return {get() {track();return value;},set(newVal) {clearTimeout(timer);timer = setTimeout(() => {console.log("触发set", newVal);value = newVal;trigger();}, delay);},};});
}

二、源码学习

  • 不同的项目初始化方式,源码的位置可能不同(我是采用 vite 创建的项目)
  • 源码位置我查阅的是:node_modules/@vue/reactivity/dist/reactivity.cjs.prod
  • 主要学习一下核心函数 createRef 基本逻辑

① 源码截图:

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

② 源码学习记录

/***  createRef 中*    1、若 isRef = true,则直接返回;否则走进 RefImpl(实现 ref 的类)中**    2、RefImpl:跟上面的 customRef 非常类似,原理相同(get\set,track\trigger)**        - get 时要追踪变化,trackRefValue(依赖收集)*        - set 时要触发更新,triggerRefValue -> triggerEffects(依赖更新)**            ref 和 triggerRef 在源码中都会调用 triggerRefValue -> triggerEffects,所以都会触发更新*            所以 ref 不能和 shallowRef 混用!会导致 shallowRef 被更新**    3、若 shallow 传 true(即为shallowRef)*          - _rawValue 直接返回*          - _value 直接返回**    4、若 shallow 传 false(即为 ref)*          - _rawValue 走进 toRaw 中(后续学习)*          - _value 则会走进 toReactive 中,toReactive 中先判断是不是引用类型,*                - 如果是的话调用 toReactive 函数将其变为响应式对象*                - 如果不是直接返回*          - 相当于 ref 内部实现响应式还是用的 reactive !!**/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/83434.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python篇】Python基础语法

【Python篇】Python基础语法 拖拖拖&#xff0c;能使工作便捷高效的为何要拒绝&#xff0c;作个记录—【蘇小沐】 文章目录 【Python篇】Python基础语法1.实验环境 1、标识符2、Python保留字&#xff08;关键字&#xff1a;不能用作任何标识符名称&#xff09;3、注释1&#x…

【链表OJ 3】链表的中间结点

前言: 本文收录于http://t.csdn.cn/n6UEP数据结构刷题的博客中,首先欢迎大家的来访&#xff0c;其次如有错误&#xff0c;非常欢迎大家的指正&#xff01;我会及时更正错误&#xff01; 目录 一.链表的中间结点 1.1原理:快慢指针的使用 链表元素个数为奇数时 链表元素个数…

抽象工厂模式-java实现

介绍 抽象工厂模式基于工厂方法模式引入了“产品族”的概念&#xff0c;即我们认为具体产品是固定的&#xff0c;具体产品存在等级之分&#xff0c;比如我们常说的手机&#xff0c;有“青春版”&#xff0c;“至尊版”&#xff0c;“至臻版”。一个产品有多个版本族。这时候&a…

day23-113. 路径总和ii

113. 路径总和ii 力扣题目链接(opens new window) 给定一个二叉树和一个目标和&#xff0c;找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff0c;以及目标和 sum 22&#xff0c; 思路 利用…

django中使用bootstrap-datepicker时间插件

1、插件的下载 Bootstrap Datepicker是一款基 于Bootstrap框架的日期选择控件&#xff0c;可以方便地在Web应用中添加可交互的日期选择功能。Bootstrap Datepicker拥有丰富的选项和API,支持多种日期格式&#xff0c;可以自定义样式并支持各种语言。 Bootstrap Datepicker 依赖…

【Linux】冯诺伊曼体系结构|操作系统概念理解

个人主页&#xff1a;&#x1f35d;在肯德基吃麻辣烫 我的gitee&#xff1a;Linux仓库 个人专栏&#xff1a;Linux专栏 分享一句喜欢的话&#xff1a;热烈的火焰&#xff0c;冰封在最沉默的火山深处 文章目录 前言一、先谈硬件——冯诺依曼体系结构1.什么是冯诺依曼体系结构&am…

SpringCloud整体架构概述

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; SpringCloud整体架构概述 SpringCloud对常见的分布式系统模式提供了简单易用的编程模型&#xff0c;帮助开发者构建弹性、可靠、协调的应用程序。 SpringCloud是在Spr…

汽车IVI中控开发入门及进阶(十):车载摄像头接口CVBS、AHD和MIPI

文章目录 前言一、CVBS是什么?二、AHD是什么?三、MIPI是什么?前言 汽车电子电气架构正在由传统的分布式架构向域集中式架构转变,也就是将多个应用程序集中在一个域中,正如提到IVI,有些已经开始导入域控,除了一带多的显示屏、一带多的雷达传感器,当然还有一带多的摄像头…

unity 修改默认脚本

using System.Collections; using System.Collections.Generic; using UnityEngine; //***************************************** //创建人&#xff1a; xxxx //功能说明&#xff1a; //***************************************** #ROOTNAMESPACEBEGIN# public class #SCRI…

Jenkins集成appium自动化测试(Windows篇)

一&#xff0c;引入问题 自动化测试脚本绝大部分用于回归测试&#xff0c;这就需要制定执行策略&#xff0c;如每天、代码更新后、项目上线前定时执行&#xff0c;才能达到最好的效果&#xff0c;这时就需要进行Jenkins集成。 不像web UI自动化测试可以使用无痕浏览器做到无界…

03微服务到底是什么

一句话导读 微服务是一种架构模式&#xff0c;英文翻译 microservice&#xff0c;微服务架构的核心理念是将大型、复杂的单体应用拆分成更小的、自治的组件&#xff0c;每个组件即为一个微服务 目录 一句话导读 一、微服务的定义 二、微服务的特点 1.独立性 2.松耦合 3.可伸…

营收、净利同比微增,喜临门品牌升级“临门一脚”?

8月8日晚&#xff0c;喜临门发布2023上半年业绩报告。根据财报&#xff0c;2023年上半年&#xff0c;喜临门营业收入约38.05亿元&#xff0c;同比增加5.53%&#xff1b;归属于上市公司股东的净利润约2.22亿元&#xff0c;同比增加1.2%。 如果仅从这份财报看&#xff0c;喜临门…

操作系统—调度算法

进程调度算法 进程调度算法也称CPU调度算法 调度发生时期 当进程从运行状态转到等待状态&#xff1b;当进程从运行状态转到就绪状态&#xff1b;当进程从等待状态转到就绪状态&#xff1b;当进程从运行状态转到终止状态&#xff1b; 其中发生在 1 和 4 两种情况下的调度称为…

electron+vue3全家桶+vite项目搭建【13.1】ipc通信的使用,主进程与渲染进程之间的交互

文章目录 引入IPC通信[主/渲染]进程对应渲染进程>主进程代码测试测试效果 主进程>渲染进程代码测试测试效果 双向通信代码测试测试效果 引入 electron项目常常由一个主进程和多个渲染进程构成&#xff0c;渲染进程之间是隔离的&#xff0c;而所有渲染进程都和主进程共享…

学习左耳听风栏目90天——第一天 1-90(学习左耳朵耗子的工匠精神,对技术的热爱)【洞悉技术的本质,享受科技的乐趣】

洞悉技术的本质&#xff0c;享受科技的乐趣 第一篇&#xff0c;我的感受就是 耗叔是一个热爱技术&#xff0c;可以通过代码找到快乐的技术人。 作为it从业者&#xff0c;我们如何可以通过代码找到快乐呢&#xff1f;这是一个问题&#xff1f; 至少目前&#xff0c;我还没有这种…

Vue [Day6]

路由进阶 路由模块的封装抽离 src/router/index.js import VueRouter from vue-router // 用绝对路径的方式来写目录 相当于src import Find from /views/Find import Friend from ../views/Friend import My from ../views/Myimport Vue from vue Vue.use(VueRouter)con…

在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配

1.Cadence 17.2 配置CIS数据库报&#xff1a;ERROR(ORCIS-6245): Database Operation Failed 安装cadance17.2以上版本时&#xff0c;ERROR(ORCIS-6245): Database Operation Failed_收湾湾的博客-CSDN博客 原因是ODBC数据库没有配置&#xff0c;或者没有驱动&#xff0c; 驱…

Linux(进程间通信详解)

进程间通信&#xff0c;顾名思义&#xff0c;就是进程与进程之间互通信交流&#xff0c;OS保证了各进程之间相互独立&#xff0c;但这不意味着进程与进程之间就互相隔离开&#xff0c;在不少的情况下&#xff0c;进程之间需要相互配合共同完成某项6任务&#xff0c;这就要求各进…

产品体系架构202308版

1.前言 当我们不断向前奔跑时&#xff0c;需要回头压实走过的路。不断扩张的同时把相应的内容沉淀下来&#xff0c;为后续的发展铺垫基石。 不知从何时起&#xff0c;产品的架构就面向了微服务/中台化/前后端分离/低代码化/分布式/智能化/运行可观测化的综合体&#xff0c;让…

SpringCloud实用篇4——MQ RabbitMQ SpringAMQP

目录 1 初识MQ1.1 同步和异步通讯1.1.1 同步通讯1.1.2 异步通讯 1.2 技术对比 2.快速入门2.1 安装RabbitMQ2.1.1 单机部署2.1.2集群部署 2.2 RabbitMQ消息模型2.3.导入Demo工程2.4 入门案例2.4.1 publisher实现2.4.2 consumer实现 3 SpringAMQP3.1 Basic Queue 简单队列模型3.1…