从Vue2到Vue3【四】——Composition API(第四章)

news2024/11/27 17:45:44

系列文章目录

内容链接
从Vue2到Vue3【零】Vue3简介
从Vue2到Vue3【一】Composition API(第一章)
从Vue2到Vue3【二】Composition API(第二章)
从Vue2到Vue3【三】Composition API(第三章)
从Vue2到Vue3【四】Composition API(第四章)

文章目录

  • 系列文章目录
  • 前言
  • 一、customRef
  • 二、provide 与 inject
  • 三、响应式数据的判断
  • 四、Composition API 与 Options API
  • 总结


前言

随着Vue 3的发布,我们迎来了一套强大且令人兴奋的组合式API,这为开发者带来了更多灵活性和可维护性。Vue 3的组合式API不仅改变了我们编写Vue组件的方式,还引入了一些新的组件和一些小的但实用的改变。在这篇文章中,我们将深入探讨Vue 3组合式API中的customRef、provide和inject以及响应式数据的判断,,让我们一起开始这个令人兴奋的学习之旅吧!

一、customRef

  • customRef:

    • 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
    • customRef适用于需要自定义读取和写入逻辑的场景。
    • 提供了更多灵活性,可以根据具体需求定制读取和写入的行为
    • 可以与响应式系统无缝集成,保持一致的Vue开发体验。

ref其实和customRef很相似,都可以创建响应式数据,下面说说他们的异同点

  • 相同点:
  1. 响应式: 无论是customRef还是ref都能够创建响应式的数据
  2. 访问值: 无论是customRef还是ref都能够通过.value属性来访问内部的值。(操作值时都需要加.value)
  • 区别:
  1. 创建方式: customRef需要传入一个函数,并在函数中定义自定义的读取和写入逻辑;而ref只需要传入初始值即可。

  2. 读取和写入逻辑: customRef允许你定义自己的读取和写入逻辑,可以实现更灵活的响应式行为;而ref会直接访问内部的值。

  3. 依赖追踪: customRef允许你在读取和写入逻辑中手动追踪依赖,通过track和trigger函数来实现;而ref会自动追踪读取和写入的依赖。

<template>
	<input type="text" v-model="keyword">
	<h3>{{keyword}}</h3>
</template>

<script>
	import {customRef} from 'vue'
	export default {
		name:'Demo',
		setup(){
			//自定义一个myRef
			function myRef(value,delay){
				let timer
				//通过customRef去实现自定义
				return customRef((track,trigger)=>{
					return{
						get(){
							track() //告诉Vue这个value值是需要被“追踪”的
							return value
						},
						set(newValue){
							clearTimeout(timer) // 当再次输入时清空上次的定时器 重新开启一个新的定时器
							timer = setTimeout(()=>{
								value = newValue  // 直到在delay这段时间不再输入时 才会更新模板上的值
								trigger() 通知Vue去重新解析模板
							},delay)
						}
					}
				})
			}
			let keyword = myRef('hello',500) //使用程序员自定义的ref
			return {
				keyword
			}
		}
	}
</script>

这个官方给出的案例:当用户在input输入时,下方的h3标签延迟更新( 本质上就是一个防抖)
防抖指的是在一定时间内如果再次触发该事件,那么将重新计时,直到该时间内没有再次触发,才会执行事件;而节流则是在一定时间内只能触发一次事件。在实现方面可以使用定时器或时间戳等技术来实现。其中,防抖适用于像搜索框这样需要输入完整关键字才会产生最终结果的场景;而节流则更适合于需要频繁触发但每次执行事件耗时较久的场景。

请添加图片描述

myref是自定义的一个函数,所以需要有返回值,返回的值是利用customRef自定义的响应式数据
customRef内部有getter和setter,当解析模版时需要读取值(getter),当在input输入时需要重新设置值(setter)

初始读取值时
在这里插入图片描述
修改值时
在这里插入图片描述
总结来说,customRef和ref都是Vue 3提供的用于创建响应式数据的函数,它们的主要区别在于创建方式读取和写入逻辑依赖追踪。你可以根据自己的需要选择使用哪种函数来创建响应式数据。
customRef真实场景使用要结合组件库的处理是否支持,不能很好的应用到组件库里,因为组件库里都有自己的数据劫持
响应式实现原理数据劫持这块,在讲完vue3的基本使用后,会出一篇文章详细讲解,欢迎订阅本系列,长期更新!

二、provide 与 inject

  • provide 与 inject
    • provide和inject是一对用于实现父组件向子孙组件传递数据的特殊组合。它们可以帮助我们在组件树中跨层级地共享数据,而无需通过逐层传递props的方式。

    • provide 函数接收两个参数:provide( name,value ),

      • name:定义 提供给子孙们数据的 name 。
      • value :提供数据的值。
    • inject(name,default)

      • name:接收 provide 提供的属性名。

      • default:设置默认值,是可选参数。
        当父亲没有provide值时,子组件注入使用的就是默认值,默认值也没有的话就是undefined

父组件用一个 provide 选项来提供数据,后代组件用一个 inject 来接收并使用这些数据

父组件代码

<template>
  <div class="app">
    <h3>我是App组件(祖),{{ name }}--{{ price }}</h3>
    <Child />
  </div>
</template>

<script>
import { reactive, toRefs, provide } from "vue";
import Child from "./components/Child.vue";
export default {
  name: "App",
  components: { Child },
  setup() {
    let car = reactive({ name: "奔驰", price: "40W" });
    provide("car", car); //给自己的后代组件传递数据
    setTimeout(() => {
      // 过一秒钟修改父亲的car 看下子组件数据是否改变 若改变 则说明传递给子孙组件的数据也是响应式的
      car.name = '宝马'
    }, 1000);
    return { ...toRefs(car) };
  },
};
</script>

<style>
.app {
  background-color: gray;
  padding: 10px;
}
</style>

子组件代码

<template>
	<div class="child">
		<h3>我是Child组件(子),{{ name }}--{{ price }}</h3>
		<Son/>
	</div>
</template>

<script>
	import {inject, toRefs} from 'vue'
	import Son from './Son.vue'
	export default {
		name:'chIld',
		components:{Son},
		setup(){
			let car = inject('car')
			return {
				...toRefs(car)
			}
		} 
	}
</script>

<style>
	.child{
		background-color: skyblue;
		padding: 10px;
	}
</style>

孙组件代码

<template>
	<div class="son">
		<h3>我是Son组件(孙),{{car.name}}--{{car.price}}</h3>
	</div>
</template>

<script>
	import {inject} from 'vue'
	export default {
		name:'sOn',
		setup(){
			let car = inject('car')
			return {car}
		}
	}
</script>

<style>
	.son{
		background-color: orange;
		padding: 10px;
	}
</style>

效果 (父组件给子孙组件传递响应式数据,父亲修改值后,子孙组件数据也会变化)
请添加图片描述

Vue框架采用的是单向数据流的数据管理模式 ===> 子孙组件不允许修改从父组件传递下来的值,这样会造成数据流向不清晰加粗样式

  • 这种数据流的设计有以下几个优点:

    • 数据的流动清晰可控:数据从父组件传递到子组件,形成了明确的数据流动路径,使得数据的变化可以追溯和控制。
    • 组件的独立性:子组件只需要关心自己的数据和逻辑,不需要关心父组件的具体实现细节,提高了组件的独立性和可复用性。
    • 数据的可预测性:由于数据只能从父组件流向子组件,数据的变化只能通过父组件来触发,减少了数据的复杂性和不可预测性。

所以这里虽然是利用 provide 和 inject 在父组件和子孙组件之间传递数据,依然不能在后代组件中修改数据,为了避免这个问题,父组件在传递值时,应当利用readonly来限制子孙组件修改数据
升级版父组件传值

    provide("car", readonly(car)); //给自己的后代组件传递只读数据

子组件内修改值的后果 : 报错,并且值不能被修改,nice!

			setTimeout(() => {
				car.name = '五菱宏光'
			}, 2000);

在这里插入图片描述

三、响应式数据的判断

  • isRef: 检查一个值是否为一个ref对象
  • isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
  • isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
  • isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
<template>
	<h3>我是App组件</h3>
</template>

<script>
	import {ref, reactive,toRefs,readonly,isRef,isReactive,isReadonly,isProxy } from 'vue'
	export default {
		name:'App',
		setup(){
			let car = reactive({name:'奔驰',price:'40W'})
			let sum = ref(0)
			let car2 = readonly(car)

			console.log(isRef(sum)) //true
			console.log(isReactive(car)) //true
			console.log(isReadonly(car2)) //true
			console.log(isProxy(car)) //true
			console.log(isProxy(sum)) //false

			
			return {...toRefs(car)}
		}
	}
</script>

<style>
	.app{
		background-color: gray;
		padding: 10px;
	}
</style>

在这里插入图片描述

四、Composition API 与 Options API

  • Options API
    在Options API中,组件的各种选项(data、methods、computed、watch)是通过一个个独立的配置项来进行定义和组织的。这样的设计可能会导致代码的分散,特别是在大型组件中,很难追踪和管理各个选项之间的关联。
    请添加图片描述
  • Composition API
    在组合式API中,各种功能选项可以根据其逻辑关联性进行组合
    请添加图片描述

在组合式API中,可以使用setup()函数来组织和定义组件的逻辑。setup()函数中可以使用各种功能函数(如reactive、ref、computed等)来声明响应式数据、计算属性、事件处理函数等,而不需要将它们分散在不同的选项中。这样可以使得逻辑代码更加集中和易于维护。

另外,由于组合式API将数据和逻辑进行组合,使得组件的代码更加模块化和可复用(hooks)。不同的逻辑可以通过将不同的功能函数组合在一起来构建不同的组件,提高了代码的可维护性和可读性。

总结来说,在图中可以看到,使用组合式API可以将相关逻辑组合在一起,简化了代码结构,并提供了更好的可读性和可维护性。相比于Options API,组合式API更加灵活和强大,尤其适用于复杂的组件和大型项目。

总结

本系列到这,讲解完了组合式API,接下来将为大家带来新的组件小的改变

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

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

相关文章

os.environ[“CUDA_VISIBLE_DEVICES“]学习总结

今天发现一个很有意思的东西 import torch import os # Specify the GPU device os.environ["CUDA_VISIBLE_DEVICES"] "1" print(torch.cuda.is_available())但是如果修改下面的设置后&#xff0c;结果就变成了 import torch import os # Specify the…

【100天精通python】Day7:数据结构_列表 List的创建、删除、访问、遍历、统计、排序、推导等使用

目录 1 列表的创建 2 列表的删除 3 访问列表元素 4 遍历列表 5 添加修改删除列表元素 6 对列表进行统计和计算 7 对列表进行排序 8 列表推导式 9 多维列表 在Python中&#xff0c;列表是一种有序的可变数据类型&#xff0c;用于存储一组元素。 列表使用方括号“[] ”来…

汇编习题1-100和

.text .globl _start_start:mov r0,#0MOV r1,#0stop:cmp r1,#0x64addcc r1,r1,#0x1addcc r0,r0,r1b stop .end运行结果&#xff1a; 寄存器R0就为16进制的结果

K8S初级入门系列之四-Namespace/ConfigMap/Secret

一、前言 本章节我们继续学习Namespace、ConfigMap、Secret基础概念&#xff0c;了解他们基本用法和操作。NameSpace为命名空间&#xff0c;在同一集群中试下资源隔离。ConfigMap通过key-value的方式实现明文配置数据的保存&#xff0c;Secret与ConfigMap类似&#xff0c;不过是…

Windows下使用rocketMq

1、下载&#xff08;下载zip后解压即可&#xff09; 下载地址&#xff1a;下载 | RocketMQ 2、配置环境变量&#xff08;注意&#xff1a;该目录的下一级是bin&#xff09; 3、启动 在bin目录下使用cmd 分别输入 3.1 启动name server (下图是启动成功的显示&#xff0c;窗口…

CPU密集型和IO密集型任务的权衡:如何找到最佳平衡点

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、CPU密集型与IO密集型3.1、CPU密集型3.2、I/O密…

dp算法 力扣978、力扣139、力扣467

目录 一、力扣978978. 最长湍流子数组 - 力扣&#xff08;LeetCode&#xff09; &#xff08;一&#xff09;题目详情 &#xff08;二&#xff09;算法讲解 &#xff08;三&#xff09;代码 二、力扣139139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; &#xff0…

计网学习笔记 wireless mobile networks

无线局域网的组成 无线网络在近些年来一直是个非常流行的东西。现在的移动用户数量已经大大超过了有线用户数量&#xff0c;比例大于5:1。 实现无线网络的挑战性 从有线到无线是网络构建上一个伟大的设想&#xff0c;挑战性主要集中在wireless和mobility两个点上。 这两个是…

Express 框架的基本操作

目录 1、应用生成器 2、基本路由 2.1、在跟路由下配置 GET请求&#xff0c;返回对应相应内容。 2.2、在跟路由下配置 POST请求&#xff0c;返回对应相应内容。 2.3、在跟路由下配置 PUT请求&#xff0c;返回对应相应内容。 2.4、在根路由下配置DELETE请求&#xff0c;返回对…

【剑指offer】学习计划day4

目录 一. 前言 二.数组中重复的数字 a.题目 b.题解分析 c.AC代码 三.在排序数组中查找数字 I a.题目 b.题解分析 c.AC代码 四.0&#xff5e;n-1中缺失的数字 a.题目 b.题解分析 c.AC代码 一. 前言 本系列是针对Leetcode中剑指offer学习计划的记录与思路讲解。详情查看以下…

学习系统编程No.32【线程互斥实战】

引言&#xff1a; 北京时间&#xff1a;2023/7/19/15:22&#xff0c;昨天更新完博客&#xff0c;和舍友下了一会棋&#xff0c;快乐就是这么简单&#xff0c;哈哈哈&#xff01;总体来说&#xff0c;摆烂程度得到一定的改善&#xff0c;想要达到以前的水准&#xff0c;需要一定…

分布式 - 消息队列Kafka:Kafka分区常见问题总结

文章目录 01. Kafka 的分区是什么&#xff1f;02. Kafka 为什么需要分区&#xff1f;03. Kafka 分区有什么作用&#xff1f;03. Kafka 为什么使用分区的概念而不是直接使用多个主题呢&#xff1f;04. Kafka 分区的数量有什么限制&#xff1f;05. Kafka 分区的副本有什么作用&am…

[内网渗透]XXE-vulnhub

文章目录 [内网渗透]XXE-vulnhub环境安装信息收集解题步骤总结 [内网渗透]XXE-vulnhub 环境安装 首先在 vulnhub 下载文件&#xff1a; 将其解压为ovf格式&#xff1a; 使用vmware打开&#xff0c;新建一个虚拟机&#xff0c;然后开机&#xff0c;环境就搭好了 信息收集 由于…

【仿写spring】一、通过反射读取带有@RequestMapping与@Controller注解的类并模拟请求路径调用方法

目录 简介思路实践一、自定义注解RequestMapping&#xff0c;Controller二、路径转全限定名方法三、扫描文件夹四、通过反射来寻找有RequestMapping以及Controller的类五、获取对象实例六、通过invoke调用方法 文件结构以及测试结果1、文件结构2、TestController3、测试结果 简…

uniapp 条件编译失败,跑不起来

因为这行代码整个uniapp都跑不起来&#xff0c;谁懂救命。再说uniapp的异常提示也太反人类了<!-- <image :src"require(/ baseListItem.url)" /> -->

Linux进程控制(三)---进程替换+简易shell的实现

目录 execl() execv() execlp() execvp() 如何利用execl执行自己写的C/C可执行程序&#xff1f; 如何利用makefile同时编译两个文件 execle() execvpe() 简单shell的编写 什么是进程替换&#xff1f; 我们之前fork之后&#xff0c;是父子进程各自执行代码的一部分&am…

【人工智能】大模型平台新贵——文心千帆

个人主页&#xff1a;【&#x1f60a;个人主页】 &#x1f31e;热爱编程&#xff0c;热爱生活&#x1f31e; 文章目录 前言大模型平台文心千帆发布会推理能力模型微调 作用 前言 在不久的之前我们曾讨论过在ChatGPT爆火的大环境下&#xff0c;百度推出的“中国版ChatGPT”—文…

深度神经网络基础——深度学习神经网络基础 Tensorflow在深度学习的应用

目录 一、二、Tesnsflow入门 & 环境配置 & 认识Tensorflow三、线程与队列与IO操作神经网络基础知识1.简单神经网络2.卷积神经网络卷积层新的激活函数-Relu池化层(Pooling)计算 案例&#xff1a;Mnist手写数字图片识别卷积网络案例 一、二、Tesnsflow入门 & 环境配置…

IDEA无法链接代理The driver has not received any packets from the server.

问题如下: 1、本地部署Proxifier,且设置全局代理,截图如下 代理工具 2、通过Navicat 工具连接该远程数据库,连接正常,截图如下 3、通过IDEA或者Eclipse连接(通过代理),抛连接失败(数据库地址绝对无误),如果把数据库地址改成本地的mysql地址,可以正常连接(不用通过代理)…

mac使用mvn下载node-sass 会Binary download failed, trying source

m1 上使用nvm 以下node的版本可以直接下载&#xff08;Binary download&#xff0c;而不是 trying source&#xff09;而不用切换mac cpu架构 zhiwenwenzhiwenwendeMBP cockpit % nvm install 14.15.5 Downloading and installing node v14.15.5... Downloading https://node…