Vue3-21-组件-子组件给父组件发送事件

news2024/11/15 13:28:45

情景描述

【子组件】中有一个按钮,点击按钮,触发一个事件,
我们希望这个事件的处理逻辑是,给【父组件】发送一条消息过去,
从而实现 【子组件】给【父组件】通信的效果。

这个问题的解决就是 “发送事件” 这个操作。
本文就针对此操作进行详细的介绍。

子组件发送事件的两种方式

【子组件】 发送事件有两种方式:
方式一 : html模板中直接使用 “$emit” 的方式发送事件;
方式二 : 使用“defineEmits()” 来声明要发送的事件。
      
【子组件】在发送事件的时候也可以携带参数。
【defineEmits() 声明式的方式 可以进行类型参数的定义】

下面是案例代码:

方式一 :$emit 直接发送事件

$emit() 可以在html模板中直接使用
$emit() 的第一个参数是 发送的事件的名称,【推荐使用驼峰命名法进行命名】
$emit() 从第二个参数开始是 发送事件所携带的参数,父组件中可以直接获取到

1、无参数

子组件

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <!-- 直接指定发送的事件的名称 -->
        <button @click="$emit('sayHello')">点我发送一个事件</button>

    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

</script>
    
<style scoped>

    .childdiv{
        width: 300px;
        border: 1px solid green;
    }

</style>

父组件

<template>

    <div class="basediv">
      
        父组件msg : {{ msg }}

        <br>
        <br>
        <!-- 子组件的使用 : 监听子组件的事件  : 
        	@后面的事件名称要与子组件中的对应起来;
        	= 后面的函数名称是自己定义的要处理的逻辑-->
        <ChildComponent @say-hello="acceptSayHello"/>
    
    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 接收到子组件中的发送的事件
    const acceptSayHello = ()=>{
        console.log('父组件接收到子组件发送的事件 : sayHello')
    }
    
</script>
    
<style scoped>

    .basediv{
        width: 400px;
        height: 200px;
        border: 1px solid red;
    }
</style>

运行效果

在这里插入图片描述

2、有参数

子组件

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <button @click="$emit('sayHello',100,'这是参数2',true,{'aa':'对象参数'})">点我发送一个带参数的事件</button>

    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

</script>
    
<style scoped>

    .childdiv{
        width: 300px;
        border: 1px solid green;
    }

</style>

父组件

<template>

    
    <div class="basediv">
      
        父组件msg : {{ msg }}

        <br>
        <br>
        <!-- 子组件的使用 : 监听子组件的事件  : 
        	@后面的事件名称要与子组件中的对应起来;
        	= 后面的函数名称是自己定义的要处理的逻辑;
        	只写自己处理的函数名即可,无需写参数名,在逻辑处理中自动就会有的-->
        <ChildComponent @say-hello="acceptSayHello"/>
    
    </div>
    
  
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 接收到子组件中的发送的事件 : 参数直接在函数声明中接收即可
    const acceptSayHello = (p1:number,p2:string,p3:boolean,p4:object)=>{
        console.log('父组件接收到子组件发送的事件-带参数的 : sayHello')
        console.log('父组件接收到子组件发送的事件-p1 : ',p1)
        console.log('父组件接收到子组件发送的事件-p2 : ',p2)
        console.log('父组件接收到子组件发送的事件-p3 : ',p3)
        console.log('父组件接收到子组件发送的事件-p4 : ',p4)
    }

</script>
    
<style scoped>

    .basediv{
        width: 400px;
        height: 200px;
        border: 1px solid red;
    }
</style>

运行效果

在这里插入图片描述

方式二 :defineEmits() 声明式发送事件

defineEmits() 的声明语法 : const emitEvents = defineEmits(['事件名称1','事件名称2',...])
发送事件的方式 : emitEvents('事件名称',参数1,参数2,...)
扩展 : 通过 defineEmits() 声明事件的方式,可以使用ts 中的方法签名,使事件信息更完善。

1、无参数

子组件

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <button @click="sendEmit">点我发送一个defineEmits声明的事件</button>

    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 声明事件
    const emitsEventList = defineEmits(['sayHello'])

    // 点击按钮,发送事件
    const sendEmit = ()=>{
        console.log('子组件点击了按钮,发送事件-无参')
        emitsEventList('sayHello')
    }

</script>
    
<style scoped>

    .childdiv{
        width: 300px;
        border: 1px solid green;
    }

</style>

父组件

<template>

    <div class="basediv">
      
        父组件msg : {{ msg }}

        <br>
        <br>
        <!-- 子组件的使用 : 监听子组件的事件  : 
        	@后面的事件名称要与子组件中的对应起来;
        	= 后面的函数名称是自己定义的要处理的逻辑-->
        <ChildComponent @say-hello="acceptSayHello"/>
    
    </div>
    
  
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 接收到子组件中的发送的事件
    const acceptSayHello = ()=>{
        console.log('父组件接收到子组件发送的事件-无参数的 : sayHello')
    }

</script>
    
<style scoped>

    .basediv{
        width: 400px;
        height: 200px;
        border: 1px solid red;
    }
</style>

运行效果

在这里插入图片描述

2、有参数

子组件

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <button @click="sendEmit">点我发送一个defineEmits声明的带参数的事件</button>

    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 声明事件
    const emitsEventList = defineEmits(['sayHello'])

    // 点击按钮,发送事件 : 带参数的事件
    const sendEmit = ()=>{
        console.log('子组件点击了按钮,发送事件-带参数')
        emitsEventList('sayHello',100,'第二个参数',false,{"aa":"对象参数的第一个属性aa"})
    }

</script>
    
<style scoped>

    .childdiv{
        width: 300px;
        border: 1px solid green;
    }

</style>

父组件

<template>

    <div class="basediv">
      
        父组件msg : {{ msg }}

        <br>
        <br>
        <!-- 子组件的使用 : 监听子组件的事件  : 
        	@后面的事件名称要与子组件中的对应起来;
        	= 后面的函数名称是自己定义的要处理的逻辑-->
        <ChildComponent @say-hello="acceptSayHello"/>
    
    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 接收到子组件中的发送的事件
    const acceptSayHello = (p1:number,p2:string,p3:boolean,p4:object)=>{
        console.log('父组件接收到子组件发送的事件-带参数的 : sayHello')
        console.log('父组件接收到子组件使用defineEmits发送的事件-p1 : ',p1)
        console.log('父组件接收到子组件使用defineEmits发送的事件-p2 : ',p2)
        console.log('父组件接收到子组件使用defineEmits发送的事件-p3 : ',p3)
        console.log('父组件接收到子组件使用defineEmits发送的事件-p4 : ',p4)

    }

</script>
    
<style scoped>

    .basediv{
        width: 400px;
        height: 200px;
        border: 1px solid red;
    }
</style>

运行效果

在这里插入图片描述

补充 : 为事件标注类型的写法

【子组件】在使用defineEmits() 声明事件的时候,写成一个函数签名的方式,
指定 时间的名称和参数列表,
这样在编码的时候会有类型约束,看上去更加的规范一些。

子组件

<template>

    <!-- 子组件 -->
    <div class="childdiv">
        
        子组件 - msg : {{ msg }}
        <br>
        <button @click="sendEmit">点我发送一个defineEmits声明的带参数的有类型标注的事件</button>

    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 声明一个变量
    const msg = ref('这是子组件的msg变量')

    // 声明事件 : 使用类型标注的方式来声明 : 直接声明一个函数的意思就是
    const emitsEventList = defineEmits<{
        (e:'sayHello',id:number,namep:string):void
    }>()

    // 点击按钮,发送事件 : 带参数的事件
    const sendEmit = ()=>{
        console.log('子组件点击了按钮,发送事件-带参数')
        emitsEventList('sayHello',200,'第二个参数')
    }
     
</script>
    
<style scoped>

    .childdiv{
        width: 300px;
        border: 1px solid green;
    }

</style>

父组件

<template>

    <div class="basediv">
      
        父组件msg : {{ msg }}

        <br>
        <br>
        <!-- 子组件的使用 : 监听子组件的事件  : 
        	@后面的事件名称要与子组件中的对应起来;
        	= 后面的函数名称是自己定义的要处理的逻辑-->
        <ChildComponent @say-hello="acceptSayHello"/>
    
    </div>
    
</template>
    
<script setup lang="ts">

    import { ref } from 'vue'

    // 引入子组件
    import ChildComponent from './ChildComponent.vue'

    // 声明父组件的一个变量
    const msg = ref('这是父组件的msg变量')

    // 接收到子组件中的发送的事件
    const acceptSayHello = (p1:number,p2:string)=>{
        console.log('父组件接收到子组件发送的事件-带参数的 : sayHello')
        console.log('父组件接收到子组件使用defineEmits发送的事件-p1 : ',p1)
        console.log('父组件接收到子组件使用defineEmits发送的事件-p2 : ',p2)

    }

</script>
    
<style scoped>

    .basediv{
        width: 400px;
        height: 200px;
        border: 1px solid red;
    }
</style>

运行效果

在这里插入图片描述

在这里插入图片描述

父组件接收事件的方式

【父组件】接收事件的方式比较简单,就像监听普通元素的事件一样,可以直接使用语法糖 @ 符号来监听事件,
【注意点1】 :
	【子组件】中声明事件的时候,事件的名称 使用的 “驼峰命名法”,例如 "sayHello";
	【父组件】中监听事件的时候,需要使用 “中划线”的命名方式,例如 "@say-hello="xxxxxx""。

【注意点2】:
【父组件】中监听【子组件】的事件的时候,
如果有参数,【父组件】中的方法可以直接写参数就好了,接收的过程会自动匹配,
无需关心 参数名的问题,接收到就可以使用。

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

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

相关文章

KubeKey 离线部署 KubeSphere v3.4.1 和 K8s v1.26 实战指南

作者&#xff1a;运维有术 前言 知识点 定级&#xff1a;入门级了解清单 (manifest) 和制品 (artifact) 的概念掌握 manifest 清单的编写方法根据 manifest 清单制作 artifactKubeKey 离线集群配置文件编写KubeKey 离线部署 HarborKubeKey 离线部署 KubeSphere 和 K8sKubeKey…

2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。

2023-12-16&#xff1a;用go语言&#xff0c;给定整数数组arr&#xff0c;求删除任一元素后&#xff0c; 新数组中长度为k的子数组累加和的最大值。 来自字节。 答案2023-12-16&#xff1a; 来自左程云。 灵捷3.5 大体步骤如下&#xff1a; 算法 maxSum1 分析&#xff1…

12345、ABCDE项目符号列表文字视频怎么制作?重点内容介绍PR标题模板项目工程文件

Premiere模板&#xff0c;包含10个要点标题12345、ABCDE项目符号列表文字模板PR项目工程文件。可以根据自己的需要定制颜色。在视频的开头、中间和结尾使用。包括视频教程。 适用软件&#xff1a;Premiere Pro 2019 | 分辨率&#xff1a;19201080 (HD) | 文件大小&#xff1a;9…

金融众筹系统源码:适合创业孵化机构 附带完整的搭建教程

互联网技术的发展&#xff0c;金融众筹作为一种新型的融资方式&#xff0c;逐渐成为创业孵化机构的重要手段。为了满足这一需求&#xff0c;金融众筹系统源码就由此而生&#xff0c;并附带了完整的搭建教程。 以下是部分代码示例&#xff1a; 系统特色功能一览&#xff1a; 1.…

数据迁移测试经验分享

以下为作者观点&#xff1a; 数据迁移&#xff0c;是在保证新旧系统业务连续性的前提下&#xff0c;将数据从旧数据库迁移到新数据库的过程&#xff0c;测试前通过迁移策略和方案了解新旧系统数据如何重构与关联&#xff0c;测试过程需确保数据迁移的正确性&#xff0c;主要体…

《Linux C编程实战》笔记:一些系统调用

目录 dup和dup2函数 fcntl函数 示例程序1 示例程序2 ioctl函数 dup和dup2函数 #include <unistd.h> int dup(int oldfd); int dup2(int oldfd, int newfd): dup 函数复制 oldfd 参数所指向的文件描述符。 参数&#xff1a; oldfd&#xff1a;要复制的文件描述符的…

【TB作品】基于单片机的实验室管理系统,STM32,GM65二维码扫描模块

硬件&#xff1a; &#xff08;1&#xff09;STM32F103C8T6最小板&#xff08;&#xff09; &#xff08;2&#xff09;GM65二维码扫描模块 &#xff08;3&#xff09;DS1302实时时钟模块 &#xff08;4&#xff09;AT24C02 存储设备 &#xff08;5&#xff09;蜂鸣器 &#xf…

git 上传大文件操作 lfs 的使用

我们要先去下载 下载后安装 我最后还是下载到了D:\git\Git\bin这个目录下 如何检查是否下载成功呢&#xff0c;用 git lfs install 在命令行运行就可以查看 下面怎么上传文件呢 首先我们还是要初始化文件的 git init 下一步输入命令 git lfs install 下一步 git lfs tra…

初级数据结构(五)——树和二叉树的概念

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 初级数据结构&#xff08;四&#xff09;——队列 | NULL 下一篇-> 1、树结构&#xff08;Tree&#xff09; 1.1、树结构的特点 自然界中的树由根部开始向上生长&#xff0c;随机长出分支&…

在Node.js中MongoDB查询分页的方法

本文主要介绍在Node.js中MongoDB查询分页的方法。 目录 Node.js中MongoDB查询分页使用原生的mongodb驱动程序查询分页使用Mongoose库进行查询分页注意项 Node.js中MongoDB查询分页 在Node.js中使用MongoDB进行查询分页&#xff0c;可以使用原生的mongodb驱动程序或者Mongoose库…

AtCoder ABC周赛2023 12/10 (Sun) D题题解

目录 原题截图&#xff1a; 题目大意&#xff1a; 主要思路&#xff1a; 注&#xff1a; 代码&#xff1a; 原题截图&#xff1a; 题目大意&#xff1a; 给定两个 的矩阵 和 。 你每次可以交换矩阵 的相邻两行中的所有元素或是交换两列中的所有元素。 请问要使 变换至…

LLaMA的解读与其微调:Alpaca-LoRA/Vicuna/BELLE/中文LLaMA/姜子牙/LLaMA 2

前言 近期&#xff0c;除了研究ChatGPT背后的各种技术细节 不断看论文(至少100篇&#xff0c;100篇目录见此&#xff1a;ChatGPT相关技术必读论文100篇)&#xff0c;还开始研究一系列开源模型(包括各自对应的模型架构、训练方法、训练数据、本地私有化部署、硬件配置要求、微调…

Ubuntu22.04添加用户

一、查看已存在的用户 cat /etc/passwd 二、添加用户 sudo adduser xxx 除了密码是必须的&#xff0c;其他的都可以不填&#xff0c;直接回车即可 三、查看添加的用户 cat /etc/passwd 四、将新用户添加到sudo组 sudo adduser xxx sudo 五、删除用户 sudo delus…

H5ke15--1--文本管理器拖进来

1如图1&#xff0c;父元素没有行高&#xff0c;子元素就不继承&#xff0c;有了就变成图2 2或者直接写表格自动垂直居中&#xff0c;但是table太古老了&#xff0c;没人用这个&#xff0c;如图3 3我们父元素display: table;展示位表格&#xff0c;子元素display: table-cell;…

HTML + JavaScript 实现网页录制音频与下载

HTML JavaScript 实现网页录制音频与下载 HTML JavaScript 实现网页录制音频与下载简介getUserMediaMediaRecorder获取和处理音频流实现音频的录制和播放音频效果的处理实时语音通话的应用兼容性和 Latency 问题 项目代码运行实例参考源码下载 HTML JavaScript 实现网页录制…

WEB渗透—PHP反序列化(三)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

dockerfile创建镜像 lNMP+wordpress

dockerfile创建镜像 lNMPwordpress nginx dockernginx mysql dockermysql php dockerphp nginx vim nginx.conf vim Dockerfile docker network create --subnet172.17.0.0/16 --opt "com.docker.network.bridge.name""docker1" mynetwork docker buil…

Redis设计与实现之对象处理机制

目录 一、前言 二、对象处理机制 1、redisObject 数据结构&#xff0c;以及 Redis 的数据类型 2、 命令的类型检查和多态 3、对象共享 4、引用计数以及对象的销毁 三、对象的处理 1、Redis是如何处理字符串对象的&#xff1f; 2、Redis是如何处理列表对象的&#xff1f…

Arduino中以太网Udp通信

目录 1、测试硬件 2、程序 &#xff08;0&#xff09;头文件添加 &#xff08;1&#xff09;变量定义 &#xff08;2&#xff09;初始化程序 &#xff08;3&#xff09;循环执行程序 3、程序下载 &#xff08;1&#xff09;开发板控制器和端口号选择 &#xff08;2&am…

java基础知识④:设计模式

目录 一、设计模式 1️⃣创建型设计模式&#xff08;常用&#xff1a;单例、工厂、抽象工厂&#xff09; 2️⃣结构型设计模式&#xff08;常用&#xff1a;适配器、装饰者、外观、代理&#xff09; 3️⃣行为型设计模式&#xff08;常用&#xff1a;观察者、策略、模板方法、命…