Vue3 中的各种ref

年前搞了一个V3的需求,里面涉及了一些各种ref的使用,今天顺便总结下V3中ref家族。

ref家族

  • ref()
  • toRef
  • toRefs
  • isRef()
  • unref()
  • shallowRef
  • triggerRef
  • customRef
  • 总结

ref()

大家对于 ref 这个 API 肯定都不陌生。在 Vue3 中经常会用到它。它的作用是接收一个值并返回一个响应式的对象。我们可以通过.value 属性来访问和修改这个值。在模板中,我们可以省略.value,例如在下面的代码中,当点击按钮时,页面中的 count 会响应式地更改。

<template><div>{{ count }}<button @click="addCount">+1</button></div>
</template><script lang='ts' setup>
import { ref } from "vue"
const count = ref(1)
const addCount = () => {count.value++
}
</script>

toRef

toRef 可以根据一个响应式对象中的一个属性,创建一个响应式的 ref。同时这个 ref 和原对象中的属性保持同步,改变原对象属性的值这个 ref 会跟着改变,反之改变这个 ref 的值原对象属性值也会改变,它接收两个参数,一个是响应式对应,另一个则是属性值,例如下面代码

<template><div>{{ count.a }}{{ a }}<button @click="addCount">+1</button></div>
</template><script lang='ts' setup>
import { ref, toRef } from "vue"
const count = ref({a: 1,b: 2
})
const a = toRef(count.value, 'a')
const addCount = () => {a.value++
}
</script>

toRefs

toRefs 它可以将一个响应式对象转成普通对象,而这个普通对象的每个属性都是响应式的 ref

<template><div>{{ count.a }}{{ countAsRefs.a }}<button @click="addCount">+1</button></div>
</template><script lang='ts' setup>
import { reactive, toRefs } from "vue"
const count = reactive({a: 1,b: 2
})
const countAsRefs = toRefs(count)
const addCount = () => {countAsRefs.a.value++
}</script>

此时代码中的countAsRefs类型为

{a: Ref<number>,b: Ref<number>
}

它的属性 a 和 b 都是响应式的 ref 对象,同样的它们和原对象的 count 的属性也是保持同步的

根据它的特性我们通常用它来解构一个响应式对象而不会让其失去响应式

import { reactive, toRefs } from "vue";
const count = reactive({a: 1,b: 2,
});
const { a, b } = toRefs(count);

此时的 a 和 b 都是一个响应式的 ref 对象,并和原对象的 a 和 b 属性保持同步

isRef()

isRef 顾名思义它是用来判断某个值是否是 ref,注意:它判断不了这个值是不是 reactive(可以使用 isReactive 判断)

import { reactive, isRef, ref } from "vue";
const count = ref(1);
const testObj = reactive({a: 1,
});
console.log(isRef(count)); //true
console.log(isRef(testObj)); //false

unref()

其实它是一个语法糖

val = isRef(val) ? val.value : val;

如果是 ref 则返回它的内部值,否则则返回它本身。通过这个语法糖我们可以看出它可以对响应式对象解除响应式引用,比如我们只想获取一个响应式的值,但不想要它的响应式可以使用它解除引用。 例如

<template><div>{{ unRefAsCount }}{{ count }}<button @click="addCount">+1</button></div>
</template><script lang='ts' setup>
import { unref, ref } from "vue"
const count = ref(1)
let unRefAsCount = unref(count)
const addCount = () => {count.value++
}
</script>

代码中的 unRefAsCount 是不具备响应式的

shallowRef

通过翻译我们可以看出它是浅层的 ref,什么是浅层的 ref 呢? 与 ref 不同的是只有.value 是响应式的,再深层的属性则不具备响应式

<template><div>{{ shallowObj.a }}<button @click="addCount"> +1</button></div>
</template><script lang='ts' setup>
import { shallowRef } from "vue"const shallowObj = shallowRef({a: 1
})
const addCount = () => {//不会触发页面更新shallowObj.value.a++
}
</script>

但是如果我们将 addCount 改为修改整个.value 就会触发响应式了

const addCount = () => {let temp = shallowObj.value.a;temp++;shallowObj.value = {a: temp,};
};

triggerRef

它可以让浅层的 ref 即 shallowRef 深层属性发生改变的时候强制触发更改,比如上面触发不了响应式的代码示例加入triggerRef后

<template><div>{{ shallowObj.a }}<button @click="addCount"> +1</button></div>
</template><script lang='ts' setup>
import { shallowRef, triggerRef } from "vue"const shallowObj = shallowRef({a: 1
})const addCount = () => {shallowObj.value.a++//加入triggerRef强制触发更改triggerRef(shallowObj)
}
</script>

此时页面效果触发了响应式

customRef

顾名思义它是自定义的 ref,我们可以通过 customRef 来显式的追踪某个值的响应式变化,它接收一个函数,这个函数接受 track 和 trigger 两个函数作为参数,并返回一个带有 get 和 set 方法的对象。比如下面封装一个自定义的响应式对象 myRef,同时控制它只有值小于 4 才会触发响应式

<template><div>{{ count }}<button @click="addCount"> +1</button></div>
</template><script lang='ts' setup>
import { customRef } from "vue"
const myRef = (value: number) => {const customValue = customRef((track, trigger) => {return {get() {//通知vue需要追踪后续内容的变化,这里可以自由控制track()return value},set(newValue) {console.log(newValue);//myRef.value=xxx的xxx值//加trigger则触发响应式,通知vue更新页面,这里可以自由控制是否加triggerif(value<4)  trigger()value = newValue}}})return customValue
}const count = myRef(0)
const addCount = () => {count.value++
}
</script>

当 count 大于 4 的时候便失去了响应式

总结

  • ref(): 接收一个值并返回一个响应式的对象,可以使用.value 属性来访问和修改这个值。
  • toRef(obj, key):根据一个响应式对象中的一个属性,创建一个响应式的 ref,并且该 ref 和原对象中的属性保持同步。toRefs(obj): 将一个响应式对象转换成一个普通对象,其中普通对象的每个属性都是响应式的 ref。
  • isRef(value): 判断某个值是否是 ref 对象。
  • unref(value): 用于解除响应式引用
  • shallowRef(value): 创建一个浅层的ref,只有 value 属性是响应式的,深层的属性不具备响应式。
  • triggerRef(ref): 强制浅层的 ref发生改变时触发响应式。
  • customRef(factory): 自定义 ref 对象,可以显式地追踪某个值的响应式变化。

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

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

相关文章

Kuberntes权威指南

一、目录 二、Kubernetes入门 三、Kubernetes核心原理 四、Kubernetes开发指南 五、Kubernetes运维指南 六、Kubernetes高级案例进阶 七、Kubernetes源码导读

20240206三次握手四次挥手

TCP和UDP异同点 相同点&#xff1a;同属于传输层的协议 不同点&#xff1a; TCP ----> 稳定 1> 提供面向连接的&#xff0c;可靠的数据传输服务 2> 传输过程中&#xff0c;数据无误、数据无丢失、数据无失序、数据无重复 1、TCP会给每个数据包编上编号&#xff…

收藏:数据要素、数据资源、数据资产、数字资产的区别

01 什么是数据要素&#xff1f; 《中共中央关于坚持和完善中国特色社会主义制度推进国家治理体系和治理能力现代化若干重大的决议》&#xff08;2019&#xff09;首次将数据列为生产要素。 《关于构建更加完善的要素市场化配置体制机制的意见》&#xff08;2020.3&#xff09…

【Android-Gradle】多模块开发中,定义额外属性(全局变量),穿梭在不同的Gradle文件中(kotlin脚本版)

其他信息可以参考官网&#xff1a;https://docs.gradle.org/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtension.html#org.gradle.api.plugins.ExtraPropertiesExtension 但是本文讲一些简单应用&#xff1a; 需求1&#xff1a;根目录gradle文件定义一个全局变量 …

分享71个节日PPT,总有一款适合您

分享71个节日PPT&#xff0c;总有一款适合您 71个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1v4_fHplsf_hOJQbNPVUudg?pwd8888 提取码&#xff1a;8888 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

区块链金融科技:技术融合与挑战应对【文末送书-16】

文章目录 前言一.区块链与金融科技的融合&#xff1a;革新金融格局的技术之光1.1区块链技术简介1.2 区块链在金融科技中的应用 二.智能合约2.1 去中心化金融&#xff08;DeFi&#xff09;2.2区块链对金融科技的影响2.3数据安全性 三.区块链与金融科技【文末送书-16】3.1 粉丝福…

leetcode 算法 67.二进制求和(python版)

需求 给你两个二进制字符串 a 和 b &#xff0c;以二进制字符串的形式返回它们的和。 示例 1&#xff1a; 输入:a “11”, b “1” 输出&#xff1a;“100” 示例 2&#xff1a; 输入&#xff1a;a “1010”, b “1011” 输出&#xff1a;“10101” 代码 class Solution…

如何区分流量控制和拥塞控制?

流量控制属于通信双方协商&#xff1b;拥塞控制涉及通信链路全局。 流量控制需要通信双方各维护一个发送窗、一个接收窗&#xff0c;对任意一方&#xff0c;接收窗大小由自身决定&#xff0c;发送窗大小由接收方响应的TCP报文段中窗口值确定&#xff1b;拥塞控制的拥塞窗口大小…

安全SCDN有什么作用

当前网络安全形势日益严峻&#xff0c;网络攻击事件频发&#xff0c;攻击手段不断升级&#xff0c;给企业和个人带来了严重的安全威胁。在这种背景下&#xff0c;安全SCDN作为一种网络安全解决方案&#xff0c;受到了广泛的关注。那么&#xff0c;安全SCDN真的可以应对网络攻击…

【leetcode题解C++】77.组合 and 216.组合总和III and 17.电话号码的字母组合

77. 组合 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ] 示例 2&#xff1a; 输入&#xff1a…

在 CentOS 7上使用 Apache 和 mod_wsgi 部署 Django 应用的方法

简介 Django 是一个强大的 Web 框架&#xff0c;可以帮助您快速启动 Python 应用程序或网站。Django 包括一个简化的开发服务器&#xff0c;用于在本地测试代码&#xff0c;但对于任何与生产相关的事情&#xff0c;都需要一个更安全和功能强大的 Web 服务器。 在本指南中&…

【Vitis】基于C++函数开发组件的步骤

目录 基本步骤 关键领域 • 硬件接口&#xff1a; 任务级并行度&#xff1a; 存储器架构&#xff1a; 微观级别的最优化&#xff1a; 基本步骤 1. 基于 设计原则 建立算法架构。 2. &#xff08;C 语言仿真&#xff09; 利用 C/C 语言测试激励文件验证 C/C 代码的逻辑。…

Vue 3D轮播插件vue-carousel-3d(禁止滑动方法)

video 1.安装 npm install -S vue-carousel-3d2.在main.js全局引入&#xff1a; import Carousel3d from vue-carousel-3d; Vue.use(Carousel3d);3.或者直接在使用页面引入省略了上一步 import { Carousel3d, Slide } from vue-carousel-3d components: {Carousel3d,Slide },…

两个线程实现同步代码示例

#include<myhead.h>//1、定义无名信号量 sem_t sem;//定义生产者线程 void *task1(void *arg) {int num 5;while(num--){sleep(1);printf("我生产了一辆汽车\n");//4、释放资源sem_post(&sem);}//退出线程pthread_exit(NULL); }//定义消费者线程 void *ta…

win10没有调节亮度选项怎么办?

最近新装了win10&#xff0c;装机后”设置“-”显示“里面没有可以调节亮度的地方&#xff0c;这里记录一下解决方案。 解决方案 按WinX键&#xff0c;选择设备管理器&#xff0c;点击”显示适配器“&#xff0c;我这里默认是只有”Microsoft 基本显示适配器“&#xff0c;没有…

c++入门学习④——对象的初始化和清理

目录 对象的初始化和清理&#xff1a; why? 如何进行初始化和清理呢&#xff1f; 使用构造函数和析构函数​编辑 构造函数语法: 析构函数语法: 构造函数的分类&#xff1a; 两种分类方式&#xff1a; 三种调用方法&#xff1a; 括号法&#xff08;默认构造函数调用&…

UE中对象创建方法示例和类的理解

对象创建方法示例集 创建Actor示例 //创建一个护甲道具 AProp* armor GetWorld()->SpawnActor<AProp>(pos, rotator); 创建Component示例 UCapsuleComponent* CapsuleComponent CreateDefaultSubobject<UCapsuleComponent>(TEXT("CapsuleComponent&qu…

自动化报告pptx-python|高效通过PPT模版制造报告(三)

这是自动化报告学习的第三篇了,其他系列: 自动化报告的前奏|使用python-pptx操作PPT(一)自动化报告pptx-python|如何将pandas的表格写入PPTX(二)自动化报告pptx-python|高效通过PPT模版制造报告(三)自动化报告pptx-python|pptx 分析报告的工具包:reportgen(四)本…

C++泛型编程:模板偏特化

模板偏特化为模板提供特殊的实现&#xff0c;针对特定的模板参数或参数组合。 在模板全特化&#xff0c;所有的模板参数都被指定了具体的类型。 我们可以在泛化设计中提供一个特化版本&#xff0c;针对其中某个或者数个模板参数进行特化&#xff0c;我们可以指定一部分模板参…

Langchain ZERO_SHOT_REACT_DESCRIPTION的使用

ZERO_SHOT_REACT_DESCRIPTION 不能记住历史对话&#xff1a; import ChatGLM from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_community.tools.tavily_search import TavilySearchResults…