vue3常用的组件间通信
一 props
props 可以实现父子组件通信,props数据是只读。
1. 基本用法
在父组件中,你可以这样传递 props:
<template><ChildComponent message="Hello, Vue 3!" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';
</script>
在 Vue 3 的 <script setup>
语法中,你可以使用 defineProps 来定义 props:
<script setup>
import { defineProps } from 'vue';const props = defineProps({title: String,count: Number
});
</script>
在传统的 export default 语法中,可以这样定义:
export default {props: {title: {type: String,required: true},count: {type: Number,default: 0}}
};
2. 类型和默认值
- 类型:确保传递给组件的 props 类型正确,Vue 会进行类型检查。
const props = defineProps({title: String, // 只接受字符串count: {type: Number, // 只接受数字default: 0 // 默认值}
});
- 默认值:如果没有提供 props,组件将使用定义的默认值。
const props = defineProps({count: {type: Number,default: 0}
});
3. 组件的 props 验证
你可以定义自定义验证逻辑:
const props = defineProps({age: {type: Number,validator: value => value >= 18 // 只接受18岁及以上}
});
4. 注意事项
- 不可变性:props 是只读的,子组件不能直接修改父组件传递过来的 props。如果需要修改,应该在子组件内部创建一个本地副本:
<script setup>
import { ref, computed } from 'vue';const props = defineProps(['count']);
const localCount = ref(props.count);const increment = () => {localCount.value++;
};
</script>
- 响应式:如果 props 是对象或数组,确保你在子组件中使用时能够保持其响应性。
- 性能考虑:如果传递的 props是大型数据结构,如数组或对象,确保你的组件能够有效地处理这些数据。避免在子组件中直接进行深度操作,以防止性能问题。
- 组件封装:合理使用 props 有助于组件的封装和复用,保持组件的单一职责和可测试性。
二 自定义事件
自定义事件用于在子组件和父组件之间传递信息
1. 在子组件中触发事件
使用 emit 方法触发自定义事件:
<script setup>
import { defineEmits } from 'vue';const emit = defineEmits(['my-event']);const triggerEvent = () => {emit('my-event', 'Hello from child');
};
</script><template><button @click="triggerEvent">Trigger Event</button>
</template>
2. 在父组件中监听事件
使用 v-on 或简写 @ 监听自定义事件:
<template><ChildComponent @my-event="handleMyEvent" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';const handleMyEvent = (message) => {console.log(message); // 输出 "Hello from child"
};
</script>
3. 事件参数
子组件触发的事件可以带有参数,这些参数会传递给父组件的事件处理函数。可以传递任意类型的数据(如字符串、数字、对象等)。
// 子组件
const triggerEvent = () => {emit('my-event', 'Hello from child', 123);
};// 父组件
const handleMyEvent = (message, number) => {console.log(message, number); // 输出 "Hello from child" 123
};
4 组件解耦
子组件应通过自定义事件向父组件发送消息,而不是直接修改父组件的数据。这样可以保持组件的独立性和可重用性。
<!-- 子组件 -->
<template><button @click="notifyParent">Notify Parent</button>
</template><script setup>
import { defineEmits } from 'vue';
const emit = defineEmits(['notify']);const notifyParent = () => {emit('notify', 'Data');
};
</script><!-- 父组件 -->
<template><ChildComponent @notify="handleNotify" />
</template><script setup>
import ChildComponent from './ChildComponent.vue';const handleNotify = (data) => {console.log(data); // 输出 "Data"
};
</script>
三 v-model
在 Vue 3 中,v-model 的原理基于双向数据绑定。其核心是通过 modelValue
和 update:modelValue
事件来实现的。具体来说:
- 父组件:使用 v-model 绑定到子组件的
modelValue
属性。 - 子组件:通过
modelValue
属性接收数据,并在需要时通过emit('update:modelValue', newValue)
触发更新事件,将新值传递回父组件。
在 Vue 3 中,v-model 的默认行为可以被自定义,允许为不同的 props 和事件指定不同的名称。可以通过 v-model:propName
和 @update:propName
的方式来指定。
1 原理
v-model 实现了双向绑定,其底层机制涉及两个主要的部分:
- 数据绑定:v-model 将父组件的一个数据属性绑定到子组件的 modelValue 属性。
- 事件更新:子组件通过触发 update:modelValue 事件来通知父组件更新数据属性。
- 简化流程示意:
- 数据绑定:
<ChildComponent v-model="parentValue" />
在这个例子中,parentValue 是父组件的数据属性,v-model 将其绑定到ChildComponent 组件的 modelValue 属性上。
- 数据传递:
<input :value="modelValue" @input="updateValue" />
子组件的 input 元素将 modelValue 作为其值,并监听 input 事件。
- 事件触发:
function updateValue(event) {emit('update:modelValue', event.target.value);
}
当用户在输入框中输入内容时,子组件触发 update:modelValue 事件,将新的值传递给父组件。
2 基本用法:
在父组件中使用 v-model 绑定数据到子组件的 props 中,子组件通过 emit 触发更新:
父组件
<template><ChildComponent v-model:message="parentMessage" />
</template><script setup>
import { ref } from 'vue';
const parentMessage = ref('Hello World');
</script>
子组件
<template><input :value="message" @input="$emit('update:message', $event)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['message']);
const emit = defineEmits();
</script>
3 自定义 v-model:
Vue 3 允许自定义 v-model 的 prop 名称:
父组件
<template><CustomComponent v-model:customProp="value" />
</template><script setup>
import { ref } from 'vue';
const value = ref('Hello');
</script>
子组件
<template><input :value="customProp" @input="$emit('update:customProp', $event)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['customProp']);
const emit = defineEmits();
</script>
4 多个 v-model:
支持在一个组件上使用多个 v-model:
父组件
<template><MultipleModelComponent v-model:title="title" v-model:content="content" />
</template><script setup>
import { ref } from 'vue';
const title = ref('Title');
const content = ref('Content');
</script>
子组件
<template><input :value="title" @input="$emit('update:title', $event)" /><textarea :value="content" @input="$emit('update:content', $event)" />
</template><script setup>
import { defineProps, defineEmits } from 'vue';
const props = defineProps(['title', 'content']);
const emit = defineEmits();
</script>
四 provide 和 inject
在 Vue 3 中,provide 和 inject 是用来在组件层级中共享数据的一种机制。它们特别适用于跨级传递数据,而不需要通过每一级的 props 和事件传递。这种机制适合于较复杂的应用场景,比如主题配置、用户认证状态等。
1 provide 和 inject 的基本用法
1. provide 和 inject 的作用
- provide: 在父组件中定义,可以将数据提供给其所有子组件(包括嵌套的子组件)。
- inject: 在子组件中定义,用于接收从祖先组件提供的数据。
父组件:使用 provide 提供数据
<template><div><h1>Parent Component</h1><child-component /></div>
</template><script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';const data = 'Shared Data';
provide('sharedData', data); // 提供数据
</script>
在这个父组件中,我们使用 provide 传递了一个名为 ‘sharedData’ 的数据,所有子组件(及其嵌套的子组件)都可以通过 inject 来访问这个数据。
子组件:使用 inject 接收数据
<template><div><h2>Child Component</h2><p>{{ sharedData }}</p></div>
</template><script setup>
import { inject } from 'vue';const sharedData = inject('sharedData'); // 接收数据
</script>
在这个子组件中,我们使用 inject 来接收从父组件中提供的数据 ‘sharedData’,并可以在模板中使用它。
2 provide 和 inject 的进阶用法
1. 提供响应式数据
提供响应式数据(如 ref 或 reactive),使得数据在多个组件中保持同步。
<template><div><h1>Parent Component</h1><child-component /></div>
</template><script setup>
import { provide, ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const count = ref(0);
provide('count', count); // 提供响应式数据
</script>
在子组件中,你可以直接修改和使用这个响应式数据:
<template><div><h2>Child Component</h2><p>Count: {{ count }}</p><button @click="count++">Increment</button></div>
</template><script setup>
import { inject } from 'vue';const count = inject('count'); // 接收响应式数据
</script>
2. 使用 provide 和 inject 进行依赖注入
对于较复杂的应用,可以在多个组件之间共享更复杂的对象或函数。例如,可以用来注入服务或工具函数。
<template><div><h1>App Component</h1><child-component /></div>
</template><script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';const apiService = {fetchData() {return 'Data from API';}
};provide('apiService', apiService); // 提供服务
</script>
在子组件中,你可以注入并使用这个服务:
<template><div><h2>Child Component</h2><p>{{ data }}</p></div>
</template><script setup>
import { inject } from 'vue';const apiService = inject('apiService');const data = apiService.fetchData(); // 使用服务
</script>
3 总结
- provide: 在父组件中定义,用来提供数据或服务给其所有子组件。
- inject: 在子组件中定义,用来接收从父组件提供的数据或服务。
- 可以使用响应式数据来确保跨组件的状态同步。
- 适用于复杂的应用程序中需要跨组件传递和共享数据的场景。
- provide 和 inject 是 Vue 3 强大的功能之一,能够帮助你更灵活地管理组件之间的状态和依赖。
五 refs
$refs 是 Vue.js 提供的一种机制,用于直接访问 DOM 元素或子组件实例。你可以在模板中使用 ref 特性来为 DOM 元素或组件指定一个引用名,然后在 Vue 实例或组件的代码中通过 $refs 来访问这些引用。
在 Vue 3 中,使用 ref 访问子组件时,通常需要通过 expose 来暴露一些方法或数据,以便父组件能够访问。你需要在子组件中使用defineExpose 来明确暴露的内容。这样,父组件就可以直接通过 ref 获取到这些数据或方法
- 用法
- 访问 DOM 元素
<template><input ref="myInput" type="text" /><button @click="focusInput">Focus Input</button>
</template><script setup>
import { ref, onMounted } from 'vue';const myInput = ref(null);const focusInput = () => {myInput.value.focus(); // 访问并操作 DOM 元素
};onMounted(() => {console.log(myInput.value); // 在组件挂载后访问 DOM 元素
});
</script>
- 访问子组件实例
子组件:
在子组件中使用 defineExpose 来暴露你想要的数据或方法。例如:
<template><div>{{ internalValue }}</div>
</template><script setup>
import { ref, defineExpose } from 'vue';const internalValue = ref('Hello, World!');defineExpose({internalValue
});
</script>
父组件:
在父组件中使用 ref 获取子组件的实例,然后访问暴露的数据或方法:
<template><ChildComponent ref="child" /><button @click="showValue">Show Value</button>
</template><script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';const child = ref(null);const showValue = () => {alert(child.value.internalValue);
};
</script>
- 优缺点
优点:
- 直接访问 DOM 元素或子组件实例,适用于需要直接操作或获取 DOM 元素或组件的方法。
- 可以在组件初始化后执行 DOM 操作,避免了过早访问 DOM 元素的问题。
缺点:
- 过度使用 ref 可能会使组件的耦合度变高,使组件之间的关系变得复杂。
- 不应过多依赖 ref 来解决问题,应该优先考虑使用 props 和 events 进行数据传递和事件处理。
相关文章:
vue3常用的组件间通信
一 props props 可以实现父子组件通信,props数据是只读。 1. 基本用法 在父组件中,你可以这样传递 props: <template><ChildComponent message"Hello, Vue 3!" /> </template><script setup> import C…...
Windows 查找特定进程的ID并杀死
"*分析用户信息.py*" 换为自己的文件名 Get-WmiObject Win32_Process | Where-Object { $_.CommandLine -like "*分析用户信息.py*" } 查找后 内容如下 __GENUS : 2 __CLASS : Win32_Process __SUPERCLASS …...

Snapchat API 访问:Objective-C 实现示例
Snapchat 是一个流行的社交媒体平台,它允许用户发送和接收短暂存在的图片和视频。对于开发者来说,访问 Snapchat API 可以为应用程序添加独特的社交功能。本文将介绍如何在 Objective-C 中实现对 Snapchat API 的访问,并提供一个详细的代码示…...

ps证件照蓝底换白底
ps证件照蓝底换白底 1、打开 Photoshop,导入需要处理的照片。 2、左侧工具栏中选择“魔棒工具”,点击证件照的背景区域进行选择。 3、使用快捷键 Shift F5 或者从顶部菜单选择“编辑” -> “填充”,在弹出的对话框中选择“填充内容”中…...

阿里云kafka消息写入topic失败
1. 问题现象描述 20240918,14:22,测试反馈说kafka有问题,生产者写入消息的时候报错,并发了一张日志截图,主要报错如下: to topic xxxx: org.apache.kafka.common.errors.TimeoutException: Expiring 1 record(s) for x…...

图像放大效果示例【JavaScript】
实现效果: 当鼠标悬停在小图(缩略图)上时,大图(预览图)会随之更新为相应的小图,并高亮当前悬浮的小图的父元素。 代码: 1. HTML部分 <!DOCTYPE html> <html lang"z…...
【C#生态园】云端之C#:全面解析6种云服务提供商的SDK
C#开发者必读:深度比较6种云服务SDK 前言 随着云计算技术的迅猛发展,越来越多的企业和开发者选择将应用程序部署到公共云平台上。针对C#开发者而言,各大云服务提供商纷纷推出了适用于C#的SDK,以便开发者能够更轻松地与其云服务进…...

远程升级又双叒叕失败?背后原因竟然是。。。
最近又遇到了远程升级接连失败的情况,耐心和信心都备受折磨! 事情是这样的:有客户反馈在乡村里频繁出现掉线的情况,不敢耽搁,赶紧联系小伙伴排查测试,最后发现,只有去年某一批模块在当下环境才…...

【测试】——Selenium API (万字详解)
📖 前言:本文详细介绍了如何利用Selenium进行Web自动化测试,包括定位元素(如cssSelector和xpath)、常用操作函数(如点击、输入等)、窗口管理、键盘鼠标事件和浏览器导航,以及处理弹窗…...

Redis:原理+项目实战——Redis实战3(Redis缓存最佳实践(问题解析+高级实现))
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理项目实战——Redis实战2(Redis实现短信登录(原理剖析代码优化)&#x…...

刚刚,Stable Diffusion 2024升级,最强Ai绘画整合包、部署教程(解压即用)
2024Ai技术大爆发的元年 目前两款Ai神器大火 一款是大名鼎鼎的Chat GPT 另外一款—Stable Diffusion 堪称全球最强Ai绘画工具 Stable Diffusion Ai绘画2024版本更新啦! 从4.8.7更新至**4.9版本!**更新优化和大模型增加,无需安装…...

【AIGC】ChatGPT提示词助力高效文献处理、公文撰写、会议纪要与视频总结
博客主页: [小ᶻZ࿆] 本文专栏: AIGC | ChatGPT 文章目录 💯前言💯高效英文文献阅读提示词使用方法 💯高效公文写作提示词使用方法 💯高效会议纪要提示词使用方法 💯高效视频内容分析提示词使用方法 &a…...
centos7更换国内下载源
📖centos7更换国内下载源 在CentOS 7上更换为国内源可以通过替换 /etc/yum.repos.d/CentOS-Base.repo文件来实现。以下是一些常用的国内源以及如何更换的示例: 阿里云源: mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Bas…...

【Linux】常用指令【更详细,带实操】
Linux全套讲解系列,参考视频-B站韩顺平,本文的讲解更为详细 目录 一、文件目录指令 1、cd【change directory】指令 2、mkdir【make dir..】指令 3、cp【copy】指令 4、rm【remove】指令 5、mv【move】指令 6、cat指令和more指令 7、less和…...
力扣3290.最高乘法得分
力扣3290.最高乘法得分 递归 记忆化搜索 对于b数组,从右往左考虑取不取,如果取则问题变成b[0] ~ b[i-1]间找j - 1个数 如果不取,则问题变成b[0] ~ b[i]间找j个数即dfs(i,j) max(dfs(i-1,j) , dfs(i-1,j-1) a[j] * b[i]) 边界:…...

Python | Leetcode Python题解之第413题等差数列划分
题目: 题解: class Solution:def numberOfArithmeticSlices(self, nums: List[int]) -> int:n len(nums)if n 1:return 0d, t nums[0] - nums[1], 0ans 0# 因为等差数列的长度至少为 3,所以可以从 i2 开始枚举for i in range(2, n):i…...
深入理解 ClickHouse 的性能调优与最佳实践
1. 介绍 ClickHouse 是一款由 Yandex 开发的开源列式数据库,专为在线分析处理(OLAP)场景设计。它以极高的查询性能著称,尤其适用于大规模数据的快速聚合和分析。自发布以来,ClickHouse 在多个行业中得到了广泛应用&am…...

Elasticsearch——介绍、安装与初步使用
目录 1.初识 Elasticsearch1.1.了解 ES1.1.1.Elasticsearch 的作用1.1.2.ELK技术栈1.1.3.Elasticsearch 和 Lucene1.1.4.为什么不是其他搜索技术?1.1.5.总结 1.2.倒排索引1.2.1.正向索引1.2.2.倒排索引1.2.3.正向和倒排 1.3.Elasticsearch 的一些概念1.3.1.文档和字…...
FreeRTOS保姆级教程(以STM32为例)—任务创建和任务控制API说明
目录 一、任务创建: (1)TaskHandle_t 任务句柄 (2) xTaskCreate: 函数原型: 参数说明: 返回值: 示例: 注意事项: 用法示例:…...
Go语言现代web开发14 协程和管道
概述 Concurrency is a paradigm where different parts of the program can be executed in parallel without impact on the final result. Go programming supports several concurrency concepts related to concurrent execution and communication between concurrent e…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...