Vue3(五) 组件通信大汇总
文章目录
- 一、props
- 二、自定义事件
- 三、mitt
- 四、v-model
- 1.`v-model`的本质
- 2.`v-model`用在组件标签上
- 3.更换`modelValue`
- 4.更换`modelValue`时,可以在组件标签上多次使用`v-model`
- 五、$attrs
- 六、$refs,与¥parent
- 1. 回顾标签ref属性修改组件信息
- 2. $refs实现父修改所有子组件信息
- 3. $parent实现子修改父
- 七、provide、inject祖孙通信
- 1. 祖传孙
- 2. 孙传祖
- 八、pinia,见之前的博客
- 九、插槽slot
- 1. 默认插槽
- 2. 具名插槽
- 3. 作用域插槽
- 组件通信总结
一、props
概述:props是使用频率最高的一种通信方式,常用与 :父传子。
- 若 父传子:属性值是非函数。
- 若 子传父:属性值是函数。
父传子
<!--父组件-->
<Child :car="car" />
<script>let car = ref('奔驰')
</script><!--子组件接收数据--><h4>父亲给的车:{{ car }}</h4><script>defineProps(['car'])
</script>
子传父:
需要父提前给子传递函数,通过参数接收子传递的数据
<!--父组件--><h4 v-if="toy">子组件给的玩具:{{ toy }}</h4><Child :car="car" :sendToy="sendToy" />
<script>let toy = ref('')function sendToy(value: string) {toy.value = value}
</script><!--子组件传递数据-->
<button @click="sendToy(toy)">把玩具给子组件</button>
<script setup lang="ts" name="Child">import { ref } from 'vue'let toy = ref('奥特曼')defineProps(['car', 'sendToy'])
</script>
二、自定义事件
触发事件的语法:
let emit = defineEmits(['函数名'])// 触发事件emit('函数名',需要传递的参数)
举例:
<!--父组件自定义事件send-toy--><h4 v-show="toy">子组件传递过来的玩具:{{ toy }}</h4><Child @send-toy="getToy" />
<script>let toy = ref('')function getToy(value: string) {toy.value = value}
</script><!--子组件接收数据-->
<!--触发send-toy事件,父组件进而调用了getToy函数,并收到了参数toy--><button @click="emit('send-toy', toy)">玩具给父组件</button><script>let toy = ref('奥特曼')// 接收之后,emit('send-toy')就是在触发事件let emit = defineEmits(['send-toy'])
</script>
emit接收两个事件:
let emit = defineEmits(['a','b'])
触发时:
emit('a')
emit('b')
三、mitt
消息订阅pubsub,全局事件总线$bus,mitt都是一样的思想。
接收数据的:提前绑好事件(提前订阅消息)
提供数据的:在合适的时候触发事件(发布消息)
- 安装mitt:
npm i mitt - 新建文件:
src\utils\emitter.ts// 引入mitt import mitt from "mitt";// 创建emitter const emitter = mitt()// 创建并暴露mitt export default emitter绑定事件:
emitter.on(事件名,()=>{回调函数逻辑 })
触发事件:emitter.emit(事件名,传递的参数)
解绑事件:emitter.off(事件名)
解绑所有事件:emitter.all.clear() - 接收数据的组件绑定事件+在组件卸载前解绑事件

- 发送数据的组件触发事件

四、v-model
UI 组件库大量使用v-model进行通信。
1.v-model的本质
<!-- v-model双向绑定,用在html标签上 --><input type="text" v-model="username"><!-- 上边代码的本质是: --><!-- :value="username":实现数据到页面@input...:实现页面到数据--><input type="text" :value="username" @input="username = (<HTMLInputElement>$event.target).value">
(<HTMLInputElement>$event.target).value其实就是$event.target.value,因为ts语法的限制,需要加断言。
2.v-model用在组件标签上
<!-- 修改modelValue -->
<ChildInput v-model="username" />
<!-- 本质是:默认写modelValue,也可以修改,修改见第3点更换modelValue -->
<ChildInput :modelValue="username" @update:modelValue="username = $event" />
:modelValue="username":props实现父传子
@update...:类似于自定义事件,实现子传父;$event是子组件传过来的值
ChildInput 组件中:
<template><!--将接收的modelValue值赋给input元素的value属性,目的是:为了呈现数据 --><!--给input元素绑定原生input事件,触发input事件时,进而触发update:model-value事件,触发时将$event.target.value通过参数传回去--><input type="text" :value="modelValue"@input="emit('update:modelValue', (<HTMLInputElement>$event.target).value)">
</template><script setup lang="ts" name="ChildInput">
// 接收父组件传递的值
defineProps(['modelValue'])
// 声明事件,
let emit = defineEmits(['update:modelValue'])
</script>
流程就是:
(1) 子组件将用户输入的值传给父组件:
子组件中通过触发事件将$event.target.value的值(也就是用户输入的值)传给父组件,父组件将username的值改为用户输入的值。
(2) 用户输入的值传给子组件进而呈现在页面上:
通过父组件的modelValue将新的username值传给子组件,子组件通过props接收后赋给input标签的value属性,呈现用户输入的数据。
3.更换modelValue
需要在v-model后加上别名
<!-- 修改modelValue --><ChildInput v-model:mima="password" /><!-- 本质 -->
<ChildInput :mima="username" @update:mima="username = $event" />
4.更换modelValue时,可以在组件标签上多次使用v-model

注意:
父组件中:@update:modelValue="username = $event"
子组件中: @input="emit('update:modelValue', $event.target.value)
什么时候用$event,什么时候用$event.target.value
$event是什么?什么时候能.target
- 对于原生事件,$event就是事件对象,====>能.target
- 对于自定义事件,$event就是触发事件时,所传递的数据,===>不能.target
五、$attrs
- 用来实现祖孙组件之间的通信。
- 当父组件向子组件通过props传值时,子组件``defineProps()只接收部分值,剩下没接收的值则存在了
$attrs里。
1. 未读取的数据存在$attrs里
<!-- 父组件 -->
<div class="father"><h3>父组件</h3><h4>a:{{ a }}</h4><h4>b:{{ b }}</h4><h4>c:{{ c }}</h4><h4>d:{{ d }}</h4><!-- v-bind="{ x: 100, y: 200 }" 等价于 :x="100" :y="200" --><Child :a="a" :b="b" :c="c" :d="d" v-bind="{ x: 100, y: 200 }" /><!-- 等价于 --><!-- <Child :a="a" :b="b" :c="c" :d="d" :x="100" :y="200" /> -->
</div>
<!-- 子组件 --><h4>a:{{ a }}</h4><h4>其他:{{ $attrs }}</h4><script>defineProps(['a'])</script>

2. 祖向孙传数据
<!--Father.vue--><Child :a="a" :b="b" :c="c" :d="d" v-bind="{ x: 100, y: 200 }" /><!--Child.vue,中间组件啥也不接受,传给GrandChild--><GrandChild v-bind="$attrs" /><!--GrandChild.vue--><div class="grand-child"><h3>孙组件</h3><h4>a:{{ a }}</h4><h4>b:{{ b }}</h4><h4>c:{{ c }}</h4><h4>d:{{ d }}</h4><h4>x:{{ x }}</h4><h4>y:{{ y }}</h4></div>
<script setup lang="ts" name="GrandChild">defineProps(['a', 'b', 'c', 'd', 'x', 'y'])
</script>
3. 孙向祖传数据
Father.vue:通过props传递函数
<Child :a="a" :b="b" :c="c" :d="d" v-bind="{ x: 100, y: 200 }" :updateA="updateA" /><!-- 等价于 -->
<script setup lang="ts" name="Father">function updateA(value: any) {a.value = value}
</script>
Child.vue
<!--Child.vue,中间组件啥也不接受,传给GrandChild-->
<GrandChild v-bind="$attrs" />
GrandChild.vue:调用函数
<button @click="updateA(666)">更新A</button>
<script setup lang="ts" name="GrandChild">defineProps(['a', 'b', 'c', 'd', 'x', 'y', 'updateA'])
</script>
六、$refs,与¥parent
正确的是$ref与$parent,标题打这两个术语会出错。
$refs:用于父传子
$parent:用于子传父
| 属性 | 说明 |
|---|---|
$refs | 值为对象,包含所有被ref属性标识的DOM元素或组件实例。 |
$parent | 值为对象,当前组件的父组件实例对象。 |
1. 回顾标签ref属性修改组件信息

子组件1Child1.vue
<template><div class="child1"><h3>子组件1</h3><h4> 玩具:{{ toy }}</h4><h4> 书籍:{{ book }}本</h4></div>
</template><script setup lang="ts" name="Child1">
import { ref } from 'vue';
let toy = ref('奥特曼')
let book = ref(3)
// 向外暴露出来,父组件才能读取到子组件的值
defineExpose({ toy, book })
</script>
子组件2Child2.vue结构类似:
...
<script setup lang="ts" name="Child2">
...
let computer = ref('联想')
let book = ref(6)
// 向外暴露
defineExpose({ computer, book })
</script>
父组件Father.vue修改子组件信息
<template><div class="father"><h3>父组件</h3><h4>房产有{{ house }}套</h4><button @click="changeToy">修改子组件1的玩具</button><button @click="changeComputer">修改子组件2的电脑</button><Child1 ref="c1" /><Child2 ref="c2" /></div>
</template><script setup lang="ts" name="Father">...let house = ref(4)// 获取到两个组件的实例对象let c1 = ref()let c2 = ref()function changeToy() {c1.value.toy = '小猪佩奇'}function changeComputer() {c2.value.computer = '华为'}
</script>
父组件通过ref获取子组件实例对象后,可以对其属性进行修改的前提条件时,子组件将该属性defineExpose()暴露出来。
2. $refs实现父修改所有子组件信息
父组件Father.vue:
<button @click="getAllChild($refs)">增加所有子组件的书数量</button>
<script>// 参数或者写成 refs:{[key:string]:any}function getAllChild(refs: any) {console.log('refs',refs);for (let key in refs) {// 修改所有子组件的书本属性refs[key].book += 3}}
</script>

3. $parent实现子修改父
父组件Father.vue将数据暴露出去,子组件才能获取到该属性并修改:
let house = ref(4)
defineExpose({ house })
子组件:Child1.vue
<button @click="minusHouse($parent)">卖出一套房产</button>
<script>function minusHouse(parent: any) {console.log('parent',parent);parent.house -= 1}
</script>

这里读取数据不用写.value见之前的记录。
七、provide、inject祖孙通信
$attrs实现祖孙通信了,打扰了中间层;而provide与inject不会打扰中间层。
提供数据:provide('数据或方法',数据或方法);
接收(注入)数据:inject('数据')
1. 祖传孙
祖组件:Father.vue
<script setup lang="ts" name="Father">let car = ref('奔驰')// 传递的数据,通过provide提供provide('car', car)
</script>
孙组件:GrandChild.vue
<div class="grand-child"><h3>我是孙组件</h3><h4>车子:{{ car }}</h4></div>
<script setup lang="ts" name="GrandChild">// 1.引入injectimport { inject } from 'vue'// 2. 读取数据;let car = inject('car')
</script>
注意,如果接收数据时
let car = inject('car2')
祖组件没有提供名为car2的数据,则孙组件读取到的car值是undefined;
孙组件可设置默认值
let car = inject('car2','奥迪') // car的默认值是奥迪
2. 孙传祖
思想还是祖给孙传递函数,孙通过参数的方式来给祖传信息。
祖组件:Father.vue
<script setup lang="ts" name="Father">
import { ref, provide } from 'vue';
let money = ref(500)function spendMoney(value: number) {money.value -= value
}
// 可以将数据或方法一起传递
provide('moneyContext', { money, spendMoney })
</script>
孙组件:GrandChild.vue
<div class="grand-child"><h3>我是孙组件</h3><h4>银子:{{ money }}万元</h4><h4>车子:{{ car }}</h4><button @click="spendMoney(6)">花钱</button></div><script setup lang="ts" name="GrandChild">import { inject } from 'vue'// 解构取值// let { money, spendMoney } = inject('moneyContext')// 上面的方式会有警告,ts不确定是否会有money和spendMoney,所以给个默认值let { money, spendMoney } = inject('moneyContext', { money: 0, spendMoney: (param: number) => { } })
</script>
注意:为什么传递的不是money.value,而是money?
provide('moneyContext', { money.value, spendMoney })
如果传递.value,则传递的只是一个值;

八、pinia,见之前的博客
Vue3(四) pinia
九、插槽slot
回顾Vue2插槽内容Vue2插槽
1. 默认插槽
将组件标签中的html结构放入slot所在的位置


2. 具名插槽
上边的例子中,游戏列表四个字在英雄联盟等列表的上方,是因为页面结构中<h2>游戏列表</h2>在ul的上方。
如果页面结构中<h2>游戏列表</h2>在ul的下方。如何仍旧保持这样的页面效果:

采用具名插槽,通过v-slot:插槽名或#插槽名 指定要把页面结构放在哪个插槽里。
<Category><template #s2><video video :src="videoUrl" controls></video></template><template #s1><h2>今日影视推荐</h2></template></Category>
3. 作用域插槽
子组件Game
<template><div class="game"><h2>游戏列表</h2><!-- 需要传递的值 --><slot :youxi="games" x="hh" y="hello"></slot></div>
</template><script setup lang="ts" name="Game">
import { reactive } from 'vue';
let games = reactive([{ id: 'asgytdfats01', name: '英雄联盟' },{ id: 'asgytdfats02', name: '王者农药' },{ id: 'asgytdfats03', name: '红色警戒' },{ id: 'asgytdfats04', name: '斗罗大陆' }
])
</script>
父组件Father.vue

params包含所有参数:

总结:
- 默认插槽:
- 具名插槽:
命名<slot name="xxx"></slot>;
使用:<template #xxx>或<template v-slot:xxx>- 作用域插槽
数据在子组件身上:<slot :xxx="yyy" :n1="zzz" ></slot>
父组件使用数据:
<template v-slot="params">params接收所有传递过来的数据
<template v-slot:defalut="params">通过插槽名指定接收某个插槽的数据
<template #defalut="{xxx}">通过#插槽名指定接收某个插槽的数据
组件通信总结

相关文章:
Vue3(五) 组件通信大汇总
文章目录 一、props二、自定义事件三、mitt四、v-model1.v-model的本质2.v-model用在组件标签上3.更换modelValue4.更换modelValue时,可以在组件标签上多次使用v-model 五、$attrs六、$refs,与¥parent1. 回顾标签ref属性修改组件信息2. $refs实现父修改所…...
红队信息搜集扫描使用
红队信息搜集扫描使用 红队行动中需要工具化一些常用攻击,所以学习一下 nmap 等的常规使用,提供灵感 nmap 帮助 nmap --help主机扫描 Scan and no port scan(扫描但不端口扫描)。-sn 在老版本中是 -sP,P的含义是 P…...
Python自学查漏9.28
自学查漏9.28 一、环境安装&代码执行原理&变量命名 安装 Python 代码执行原理 解析(Parsing): 当你运行一个 Python 脚本时,Python 解释器首先会解析整个代码,将其转换成一种叫做“字节码”(bytecode&…...
Java文件I/O处理之RandomAccessFile【随意存取文件】
Java语言有一个处理文件输入输出的RandomAccessFile类,既可以读取文件内容,也可以向文件输出数据。 RandomAccessFile类在国内的技术文档和书籍中都翻译为“随机访问文件”类,确实令人不解。 在中文中“随机”的意思: 不设任何条…...
Android页面跳转与返回机制详解
在Android开发中,页面跳转是实现应用功能交互的重要手段之一。本文将从Activity之间的跳转、Activity与Fragment之间的跳转、Fragment之间的跳转以及页面返回的问题四个方面进行详细解析。 一、Activity之间的跳转 Activity是Android应用的基本构建块,…...
Elasticsearch学习笔记(1)
初识 Elasticsearch 认识和安装 Elasticsearch 是由 Elastic 公司开发的一套强大的搜索引擎技术,属于 Elastic 技术栈的一部分。完整的技术栈包括: Elasticsearch:用于数据存储、计算和搜索。Logstash/Beats:用于数据收集。Kib…...
react是一种语言?
React 不是一种编程语言,而是一种用于构建用户界面的 JavaScript 库。它由 Facebook 开发,并广泛用于开发单页应用程序(SPA)。React 允许你将 UI 拆分成独立的、可复用的组件,这些组件可以接收输入(称为“p…...
如何区分这个ip是真实ip,不是虚假的ip
区分一个IP地址是真实IP还是虚假IP(伪造IP)是非常重要的,特别是在网络安全、数据采集和其他与IP相关的业务场景中。虚假IP(也称为伪造IP或假冒IP)可以通过多种方式被创建,如代理、VPN、或IP欺骗(…...
【软件测试】详解软件测试中的测试级别
目录 一、测试级别二、组件测试三、开发者测试3.1测试与调试3.2 组件测试目标3.3 测试功能 四、稳健性测试4.1 效率的测试4.2 测试可维护性4.3 测试策略4.4 白盒测试 一、测试级别 软件系统通常是由许多子系统组成的,而这些子系统又是由多个组件组成的,…...
一条sql在MySQL中是怎么执行的
目录 一、MySQL总体架构二、各层的作用1、连接层2、应用层3、存储引擎层 一、MySQL总体架构 作为常问八股文,相信不少小伙伴当年都被问到过这个问题,回答这个问题我们首先得知道MySQL服务器基本架构,主要分为连接层,应用层和存储…...
Git | Dockerized GitLab 安装使用(简单实操版)
1. 详细步骤 1.1 安装启动 postgresql 服务 docker pull sameersbn/postgresql:14-20230628docker run --name gitlab-postgresql -d \--env DB_NAMEgitlabhq_production \--env DB_USERgitlab --env DB_PASSpassword \--env DB_EXTENSIONpg_trgm,btree_gist \--volume /srv/…...
SpringCloud简介 Ribbon Eureka 远程调用RestTemplate类 openfeign
〇、SpringCloud 0.区别于单体项目和soa架构,微服务架构每个服务独立,灵活。 1. spring cloud是一个完整的微服务框架,springCloud包括三个体系: spring cloud Netflix spring cloud Alibaba spring 其他 2.spring cloud 版本命名…...
微信小程序开发系列之-微信小程序性能优化
微信小程序开发系列之-微信小程序性能优化 性能优化是任何应用开发中的重要组成部分,尤其是在移动环境中。对于微信小程序而言,随着用户量的增加和应用功能的丰富,性能优化显得尤为关键。良好的性能不仅提升用户体验,还能增加用户…...
线程池面试集
目录 线程池中提交一个任务的流程是怎样的? 线程池有五种状态 如何优雅的停止一个线程? 线程池的核心线程数、最大线程数该如何设置? 如何理解Java并发中的可见性、原子性、有序性? Java死锁如何避免? 线程池中提交一个任务的流程是怎样的? 线程池有五种状态 如何优…...
从密码学看盲拍合约:智能合约的隐私与安全新革命!
文章目录 前言一、什么是盲拍合约?二、盲拍合约的优势1.时间压力的缓解2.绑定与秘密的挑战 三、盲拍合约的工作原理1.提交盲出价2.披露出价3.结束拍卖4.退款机制 四、代码示例总结 前言 随着区块链技术的发展,智能合约在各种场景中的应用越来越广泛。盲…...
c++学习笔记(47)
七、_public.cpp #include "_public.h" // 如果信号量已存在,获取信号量;如果信号量不存在,则创建它并初始化为 value。 // 如果用于互斥锁,value 填 1,sem_flg 填 SEM_UNDO。 // 如果用于生产消费者模型&am…...
软件设计之SSM(1)
软件设计之SSM(1) 路线图推荐: 【Java学习路线-极速版】【Java架构师技术图谱】 尚硅谷新版SSM框架全套视频教程,Spring6SpringBoot3最新SSM企业级开发 资料可以去尚硅谷官网免费领取 学习内容: Spring框架结构SpringIoC容器SpringIoC实践…...
STM32F745IE 能进定时器中断,无法进主循环
当你遇到STM32F745IE这类问题,即能够进入定时器中断但无法进入主循环(main() 函数中的循环),可能的原因和解决方法包括以下几个方面: 检查中断优先级和嵌套: 确保没有其他更高优先级的中断持续运行并阻止了主循环的执行。使用调试工具查看中断的进入和退出情况。检查中断…...
《凡人歌》中的IT职业启示录
《凡人歌》是由中央电视台、正午阳光、爱奇艺出品,简川訸执导,纪静蓉编剧,侯鸿亮任制片,殷桃、王骁领衔主演,章若楠、秦俊杰、张哲华、陈昊宇主演的都市话题剧 ,改编自纪静蓉的小说《我不是废柴》。该剧于2…...
go libreoffice word 转pdf
一、main.go 关键代码 完整代码 package mainimport ("fmt""github.com/jmoiron/sqlx""github.com/tealeg/xlsx""log""os/exec""path/filepath" ) import _ "github.com/go-sql-driver/mysql"import &q…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
mac:大模型系列测试
0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何,是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试,是可以跑通文章里面的代码。训练速度也是很快的。 注意…...
