Vue3中的常见组件通信之props和自定义事件

本文主要是介绍Vue3中的常见组件通信之props和自定义事件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Vue3中的常见组件通信

概述

​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refsparent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。

组件关系传递方式
父传子1. props
2. v-model
3. $refs
4. 默认插槽、具名插槽
子传父1. props
2. 自定义事件
3. v-model
4. $parent
5. 作用域插槽
祖传孙、孙传祖1. $attrs
2. provide、inject
兄弟间、任意组件间1. mitt
2. pinia

​ 本文讲述props和自定义事件,其他的通信方式后面再更新。

1.props

1.1 准备父子组件

首先准备一个简单的父子组件的样式,如下是父组件代码:

<template><div class="father"><h2>这是父组件</h2><Child/></div>
</template><script setup lang="ts" name="Father">//引入子组件import Child from './Child.vue';</script><style scoped>.father{margin: 5px;background-color:rgb(205, 165, 32);padding: 20px;color: white;}
</style>

以下是子组件代码:

<template><div class="child"><h2>这是子组件</h2></div>
</template><script setup lang="ts" name="Child"></script><style scoped>.child{margin: 5px;background-color: rgba(93, 135, 20, 0.224);border: 1px solid;border-color: white;box-shadow: 0 0 5px;padding: 10px;color: #000;}	
</style>

运行结果如下所示:

image-20240601203254108

1.2 父传子通信的实现

用props实现父传子通信,可以用标签中的属性值直接传递数据,父组件代码中只需要在子组件标签上添加属性值即可,如下代码,传递两个数据:

<Child :f2CMsg="f2CMsg" :f2CObj="f2CObj"/>

定义传递的数据内容,两个数据分别是ref定义的基本类型的响应式数据和reactive定义的对象类型的响应式数据。

//引入ref和reactive
import {ref,reactive} from 'vue'//数据,ref定义的基本类型的响应式数据
let f2CMsg =ref('你好,子组件。')//数据,reactive定义的对象类型的响应式数据
let f2CObj = reactive({
id:"asdfg01",
name:"张三",
age:18,
detail:"这是父组件中的对象信息"
})

在子组件中需要声明接收数据props,注意接收的数据格式是数组,哪怕是只传递一个数据也要写成数组的形式。

//声明接收数据props
defineProps(['f2CMsg','f2CObj'])

子组件中在页面展示接收的数据,如下代码:

<h4>父组件传递的信息:{{ f2CMsg }}</h4>
<h4>父组件传递的对象:</h4>
<ul><li>姓名:{{f2CObj.name}}</li><li>年龄:{{f2CObj.age}}</li><li>详情:{{f2CObj.detail}}</li>
</ul>

然后运行结果如下:

image-20240601211035944

1.3 子传父通信的实现

用props实现子传父的通信需要父组件先向子组件传递一个函数,然后传递的数据以参数的形式传递给函数,父组件中先定义子传父的数据变量和函数或者方法如下:

//定义子传父的数据变量
let c2FMsg = ref('')
//定义方法传递给子组件
function getMsg(value:string){c2FMsg.value = value
}

在标签中把方法传给子组件:

<Child :f2CMsg="f2CMsg" :f2CObj="f2CObj" :sendMsg="getMsg"/>

在子组件中接收数据,并定义数据内容:

defineProps(['f2CMsg','f2CObj','sendMsg'])
let c2FMsg = ref('你好,父组件。')

在子组件中设置一个按钮,给按钮绑定点击事件,点击事件触发sendMsg方法,并传递参数:

<button @click="sendMsg(c2FMsg)">点我向父组件传递信息</button>

现在数据应该已经传递给了父组件,在父组件可以用如下代码展示:

<h4 v-show="c2FMsg">子组件传递的信息:{{ c2FMsg }}</h4>

运行结果如下:

image-20240601213552916

点击按钮后运行结果如下:

image-20240601213621311

至此我们已经用props实现了子传父的通信功能。当然子传父也可以传递对象。此处不再展示。如下是完整代码:

父组件中的代码:

<template><div class="father"><h2>这是父组件</h2><h4 v-show="c2FMsg">子组件传递的信息:{{ c2FMsg }}</h4>	<Child :f2CMsg="f2CMsg" :f2CObj="f2CObj" :sendMsg="getMsg"/>	</div>
</template><script setup lang="ts" name="Father">//引入子组件import Child from './Child.vue';//引入ref和reactiveimport {ref,reactive} from 'vue'//数据,ref定义的基本类型的响应式数据let f2CMsg =ref('你好,子组件。')//数据,reactive定义的对象类型的响应式数据let f2CObj = reactive({id:"asdfg01",name:"张三",age:18,detail:"这是父组件中的对象信息"})//定义子传父的数据变量let c2FMsg = ref('')//定义方法传递给子组件function getMsg(value:string){c2FMsg.value = value		}
</script><style scoped>.father{margin: 5px;background-color:rgb(205, 165, 32);padding: 20px;color: white;}
</style>

子组件的代码:

<template><div class="child"><h2>这是子组件</h2><h4>父组件传递的信息:{{ f2CMsg }}</h4><h4>父组件传递的对象:</h4><ul><li>姓名:{{f2CObj.name}}</li><li>年龄:{{f2CObj.age}}</li><li>详情:{{f2CObj.detail}}</li></ul><button @click="sendMsg(c2FMsg )">点我向父组件传递信息</button></div>
</template><script setup lang="ts" name="Child">
import { ref,reactive } from 'vue';//声明接收数据props
defineProps(['f2CMsg','f2CObj','sendMsg'])let c2FMsg = ref('你好,父组件。')</script><style scoped>.child{margin: 5px;background-color: rgba(93, 135, 20, 0.224);border: 1px solid;border-color: white;box-shadow: 0 0 5px;padding: 10px;color: #000;}	
</style>

1.4 小结

用props实现父子通信的步骤是这样的:

父传子:父组件中定义传递的数据–>标签中用属性值直接传递数据–>子组件中声明接收数据–>用插值语法展示数据。

子传父: 父组件先定义接收数据的变量–>父组件中定义函数–>将函数传递给子组件–>子组件中声明接收数据,接收的数据为函数–>子组件中定义传递的数据–>子组件中调用接收的函数,将定义的要传递的数据作为参数进行传递–>父组件中收到数据,可以在页面中展示。

最后总结如下:

父传子:标签中的属性值是非函数

子传父:标签中的属性值是函数

2. 自定义事件

自定义事件通常用于子传父,需要注意在原生事件中事件名是特定的,比如click,keyup等,在自定义事件中事件名是任意的;在原生事件中事件对象 e v e n t 是包含事件相关信息的对象( ‘ p a g e X ‘ 、 ‘ p a g e Y ‘ 、 ‘ t a r g e t ‘ 、 ‘ k e y C o d e ‘ ),在定义事件中事件对象 event是包含事件相关信息的对象(`pageX`、`pageY`、`target`、`keyCode`),在定义事件中事件对象 event是包含事件相关信息的对象(pageXpageYtargetkeyCode),在定义事件中事件对象event是调用emit所提供的数据,可以是任意类型。

2.1 准备父子组件

父子组件代码与样式与本文中1.1中的完全相同,此处不再赘述。

2.2 自定义事件实现子传父通信

首先在子组件中定义要传递的数据,此次依然已字符串为例,如下代码:

let c2FMsg = ref('你好,父组件。')

然后在父组件中定义接收的数据变量,并声明函数,用来保存接收的数据。

let c2FMsg = ref('')//声明函数saveMsg,用来保存接收的数据
function saveMsg(value:string){c2FMsg.value = value
}

之后给子组件绑定自定义事件,事件名为send-message,同时将函数saveMsg传进去,注意自定义事件名的命名规范官方建议采用肉串形式的命名方式。

<!-- 给子组件绑定自定义事件 -->
<Child @send-message="saveMsg"/>

在子组件中需要声明事件

//声明事件
let emit = defineEmits(['send-message'])

触发事件的代码如下:

emit('send-message')

只要在子组件中写出上面触发事件的代码,就可以实现子传父的通信,这次以子组件挂载3秒后自动触发事件为例,如下代码:

//组件挂载3秒后触发事件
onMounted(()=>{setTimeout(()=>{//触发事件send-message,并传c2FMsgemit('send-message',c2FMsg)},3000)
})

此时已经实现了子传父的通信,最后在父组件中展示出来,如下代码:

<h3 v-show="c2FMsg">子组件传递的信息:{{ c2FMsg }}</h3>

最后运行页面效果如下,在刚启动页面是如下效果:

image-20240602105624203

3秒钟之后看下的效果如下图所示:

image-20240602105712057

以下是完整代码:

父组件代码:

<template><div class="father"><h2>这是父组件</h2><h3 v-show="c2FMsg">子组件传递的信息:{{ c2FMsg }}</h3><!-- 给子组件绑定自定义事件 --><Child @send-message="saveMsg"/></div></template><script setup lang="ts" name="Father">//引入子组件import Child from './Child.vue';import { ref } from 'vue';let c2FMsg = ref('')//声明函数,用来保存接收的数据function saveMsg(value:string){c2FMsg.value = value}</script><style scoped>.father{margin: 5px;background-color:rgb(205, 165, 32);padding: 20px;color: white;}</style>

以下是子组件代码:

<template><div class="child"><h2>这是子组件</h2></div></template><script setup lang="ts" name="Child">import {ref,onMounted} from 'vue'let c2FMsg = ref('你好,父组件。')//声明事件let emit = defineEmits(['send-message'])//组件挂载3秒后触发事件onMounted(()=>{setTimeout(()=>{//触发事件send-message,并传c2FMsgemit('send-message',c2FMsg)},3000)})</script><style scoped>.child{margin: 5px;background-color: rgba(93, 135, 20, 0.224);border: 1px solid;border-color: white;box-shadow: 0 0 5px;padding: 10px;color: #000;}	</style>

2.3 小结

以上便是自定义事件的基本用法,在实际开发中是比较常用的用来实现子传父的通信方式。

这篇关于Vue3中的常见组件通信之props和自定义事件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1026826

相关文章

Vue和React受控组件的区别小结

《Vue和React受控组件的区别小结》本文主要介绍了Vue和React受控组件的区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录背景React 的实现vue3 的实现写法一:直接修改事件参数写法二:通过ref引用 DOMVu

Java实现将HTML文件与字符串转换为图片

《Java实现将HTML文件与字符串转换为图片》在Java开发中,我们经常会遇到将HTML内容转换为图片的需求,本文小编就来和大家详细讲讲如何使用FreeSpire.DocforJava库来实现这一功... 目录前言核心实现:html 转图片完整代码场景 1:转换本地 HTML 文件为图片场景 2:转换 H

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

Vite 打包目录结构自定义配置小结

《Vite打包目录结构自定义配置小结》在Vite工程开发中,默认打包后的dist目录资源常集中在asset目录下,不利于资源管理,本文基于Rollup配置原理,本文就来介绍一下通过Vite配置自定义... 目录一、实现原理二、具体配置步骤1. 基础配置文件2. 配置说明(1)js 资源分离(2)非 JS 资

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

聊聊springboot中如何自定义消息转换器

《聊聊springboot中如何自定义消息转换器》SpringBoot通过HttpMessageConverter处理HTTP数据转换,支持多种媒体类型,接下来通过本文给大家介绍springboot中... 目录核心接口springboot默认提供的转换器如何自定义消息转换器Spring Boot 中的消息

MySQL ORDER BY 语句常见用法、示例详解

《MySQLORDERBY语句常见用法、示例详解》ORDERBY是结构化查询语言(SQL)中的关键字,隶属于SELECT语句的子句结构,用于对查询结果集按指定列进行排序,本文给大家介绍MySQL... 目录mysql ORDER BY 语句详细说明1.基本语法2.排序方向详解3.多列排序4.常见用法示例5.

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Linux中的自定义协议+序列反序列化用法

《Linux中的自定义协议+序列反序列化用法》文章探讨网络程序在应用层的实现,涉及TCP协议的数据传输机制、结构化数据的序列化与反序列化方法,以及通过JSON和自定义协议构建网络计算器的思路,强调分层... 目录一,再次理解协议二,序列化和反序列化三,实现网络计算器3.1 日志文件3.2Socket.hpp