vue3父组件调用子组件el-dialog对话框

vue3父组件调用子组件el-dialog对话框

在写项目的时候,经常要使用父子组件通讯,我已经写了很多篇博客来介绍父子组件通讯了,vue中的父子组件通讯方式有差不多10来种,最常用的就那么一两种,这里我介绍其中我认为最基础的两种。因为目标是在父组件中,通过点击按钮事件来打开子组件中的el-dialog对话框,所以比传统的父传子要复杂一点。

先捋一下逻辑:

  1. 父组件中,点击按钮,给子组件传递一个打开对话框的信息

image-20231212180558769

  1. 子组件接收数据,控制对话框显示

image-20231212180714023

一、基础的props/emits父子传值

先看看父组件中的写法

<template><BreadCrumb ref="breadCrumb" :item="item"></BreadCrumb><div class="table-wrapped"><div class="table-top"><div class="table-header"><div class="search-wrapped"><el-input v-model="input1" class="w-50 m-2" placeholder="输入账号搜索" :prefix-icon="Search" /></div><div class="button-wrapped"><el-button type="primary" @click="create">添加产品管理员</el-button></div></div></div></div><CreateAdmin :isShow="isShowDialog"></CreateAdmin>
</template><script setup>
import { ref, onMounted } from 'vue'
import { Search } from '@element-plus/icons-vue'
import BreadCrumb from '@/components/BreadCrumb.vue';
import CreateAdmin from '../components/CreateAdmin.vue'const isShowDialog = ref(false)
const item = ref({first: '用户管理',second: '产品管理员'
})
const input1 = ref('')
const tableData = ref([])
const create = () => {isShowDialog.value = true
}
</script><style lang="scss" scoped></style>

父组件中的逻辑是,点击按钮后,将isShowDialog的值改为true,同时把isShowDialog赋值给isShow传递给子组件

再看看子组件中的写法:

<template><el-dialog v-model="dialogVisible" title="创建管理员" width="30%" center></el-dialog>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'const dialogVisible = ref(false)
const props = defineProps({isShow: {type: Boolean,default: false}
})watch(() => props.isShow, (val) => {console.log(val)dialogVisible.value = val
}, { immediate: true })</script>
<style scoped></style>

子组件定义props接收父组件传递过来的值,然后赋值给dialogVisible,el-dialog根据这个dialogVisible来控制对话框是否展示

而且还使用watch深度监视了isShow的变化,当值变化时,马上把最新的值传递给dialogVisible

理论上,这样是不是可以很好的控制对话框的打开与关闭呢?实际上,根本就没法控制,也不能这么说,就第一次可以控制,然后关闭对话框后,就没法正常打开对话框了,什么原因呢,因为在关闭对话框的时候,没用通知父组件来修改对应的值,所以只能正常执行一次。来梳理一下上面代码的逻辑:

  1. 父组件传递给子组件isShow的初始值为false
  2. 父组件中点击按钮后,修改了isShow的值为true
  3. 子组件中的watch监听到isShow的变化,将最新的值(true)赋值给dialogVisible,从而控制对话框的打开
  4. 子组件关闭对话框,dialogVisible的值变为false
  5. 当再次点击父组件按钮想要打开对话框的时候,由于isShow的值仍然为true,所以子组件根本就没有监听到父组件传递过来的isShow的变化,所以对话框就再也打不开了

因此,上面的逻辑中缺少一项,就是在关闭对话框的时候,子组件给父组件传递信号,将isShow的值改为false

因此正确的写法应该是这样的:

父组件:

<template><BreadCrumb ref="breadCrumb" :item="item"></BreadCrumb><div class="table-wrapped"><div class="table-top"><div class="table-header"><div class="search-wrapped"><el-input v-model="input1" class="w-50 m-2" placeholder="输入账号搜索" :prefix-icon="Search" /></div><div class="button-wrapped"><el-button type="primary" @click="create">添加产品管理员</el-button></div></div></div><CreateAdmin :isShow="isShowDialog" @close="closeDialog"></CreateAdmin>
</template><script setup>
import { ref, onMounted } from 'vue'
import { Search } from '@element-plus/icons-vue'
import BreadCrumb from '@/components/BreadCrumb.vue';
import CreateAdmin from '../components/CreateAdmin.vue'const isShowDialog = ref(false)
const item = ref({first: '用户管理',second: '产品管理员'
})
const input1 = ref('')
const tableData = ref([])
const create = () => {isShowDialog.value = true
}
const closeDialog = (val) => {isShowDialog.value = val
}
</script><style lang="scss" scoped></style>

子组件:

<template><el-dialog v-model="dialogVisible" title="创建管理员" width="30%" center @close="closeDialog"></el-dialog>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import { creatAdminAPI } from "@/apis/userinfo";const dialogVisible = ref(false)
const props = defineProps({isShow: {type: Boolean,default: false}
})const emits = defineEmits(['close'])
const closeDialog = () => {emits('close', false)
}watch(() => props.isShow, (val) => {console.log(val)dialogVisible.value = val
}, { immediate: true })</script>
<style scoped></style>

先看子组件,在子组件的el-dialog对话框中,除了v-model="dialogVisible"这个关键属性外,还定义了它的关闭事件,当关闭对话框的时候,子组件向父组件发送一个close指令,并传递一个false值给父组件

再看父组件,父组件接收close事件,并在closeDialog中将isShowDialog的值设置为子组件传递过来的值,也就是false

这样,就可以来回控制了

也就是说,控制对话框的打开关闭,实际上要实现父传子和子传父两个过程,复杂就复杂在这里

这也是我不推荐用这种方式的原因

二、使用第三方工具mitt.js

我现在凡是涉及到父子组件传值,第一个想到的就是mitt,在vue2中,它是内置的api,叫事件总线,不知道为啥vue3移除了。mitt可以实现任意组件中的通讯,父子、兄弟、祖孙等等。

我之前写过一篇博客,专门用来解释vue3中使用第三方插件mitt实现任意组件通讯

这篇博客可能应用场景太复杂了,用在今天这个例子我觉得正合适。

使用步骤如下:

  1. 安装第三方包,并封装后导出,这个步骤我在之前的博客中已经写了详细的步骤
  2. 父组件中点击按钮后,发出打开对话框指令,代码如下,从代码中可以看出,不需要经过繁琐的传值过程,直接发送emit的openDialog指令就行了
<template><BreadCrumb ref="breadCrumb" :item="item"></BreadCrumb><div class="table-wrapped"><div class="table-top"><div class="table-header"><div class="search-wrapped"><el-input v-model="input1" class="w-50 m-2" placeholder="输入账号搜索" :prefix-icon="Search" /></div><div class="button-wrapped"><el-button type="primary" @click="create">添加产品管理员</el-button></div></div></div><CreateAdmin></CreateAdmin>
</template><script setup>
import { ref, onMounted } from 'vue'
import { Search } from '@element-plus/icons-vue'
import BreadCrumb from '@/components/BreadCrumb.vue';
import CreateAdmin from '../components/CreateAdmin.vue'
import mitt from '@/utils/mitt'
const emitter = mittconst item = ref({first: '用户管理',second: '产品管理员'
})
const input1 = ref('')
const tableData = ref([])
const create = () => {emitter.emit('openDialog')
}</script><style lang="scss" scoped></style>
  1. 子组件接收指令,代码如下,同样,子组件也不用再给父组件传递自定义事件,接收到openDialog指令后,修改dialogVisible的值为true就行了
<template><el-dialog v-model="dialogVisible" title="创建管理员" width="30%" center></el-dialog>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import { creatAdminAPI } from "@/apis/userinfo";
import mitt from '@/utils/mitt'
const emitter = mittconst dialogVisible = ref(false)emitter.on('openDialog', () => {dialogVisible.value = true
})
</script>
<style scoped></style>

两者一对比,就发现使用mitt真的会清爽多了,这也是我为啥钟情mitt的原因

如果要存储数据,可以使用mitt结合pinia或者vuex

三、使用ref控制

还有一种更简单的控制方式,不需要mitt,使用ref来实现

父组件:

<template><BreadCrumb ref="breadCrumb" :item="item"></BreadCrumb><div class="table-wrapped"><div class="table-top"><div class="table-header"><div class="search-wrapped"><el-input v-model="input1" class="w-50 m-2" placeholder="输入账号搜索" :prefix-icon="Search" /></div><div class="button-wrapped"><el-button type="primary" @click="create">添加产品管理员</el-button></div></div></div><CreateAdmin ref=createRef></CreateAdmin>
</template><script setup>
import { ref, onMounted } from 'vue'
import { Search } from '@element-plus/icons-vue'
import BreadCrumb from '@/components/BreadCrumb.vue';
import CreateAdmin from '../components/CreateAdmin.vue'const item = ref({first: '用户管理',second: '产品管理员'
})
const input1 = ref('')
const tableData = ref([])
const createRef = ref()
const create = () => {createRef.value.open()
}</script><style lang="scss" scoped></style>

子组件:

<template><el-dialog v-model="dialogVisible" title="创建管理员" width="30%" center></el-dialog>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue'
import { creatAdminAPI } from "@/apis/userinfo";const dialogVisible = ref(false)
const open = () => {dialogVisible.value = true
}
defineExpose({open
})
</script>
<style scoped></style>

可以看到,在父组件中,使用ref获取了子组件的dom,点击按钮时,调用子组件中的open方法

在子组件中,定义一个open方法,实际上就是将dialogVisible的值改为true,随后将这个open方法暴露出去

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

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

相关文章

19、命令模式(Command Pattern,不常用)

命令模式&#xff0c;将一个请求封装为一个对象&#xff08;命令&#xff09;&#xff0c;使发出请求的责任和执行请求的责任分割开&#xff0c;有效降低系统的耦合度。这样两者之间通过命令对象进行沟通&#xff0c;这样方便将命令对象进行储存、传递、调用、增加与管理。命令…

【flutter对抗】blutter使用+ACTF习题

最新的能很好反编译flutter程序的项目 1、安装 git clone https://github.com/worawit/blutter --depth1​ 然后我直接将对应的两个压缩包下载下来&#xff08;通过浏览器手动下载&#xff09; 不再通过python的代码来下载&#xff0c;之前一直卡在这个地方。 如果读者可以…

等保2.0的一些问题

测评机构的主要问题 目前国内的测评机构有199家&#xff0c;测评机构主要分为以下几类: 1)北京地区国字头的测评机构&#xff1a;全国199家测评机构中北京就占了30多家&#xff0c;几乎都是国字头的背景&#xff0c;很多挂着都是行业或者部委的名头&#xff0c;这些测评机构基本…

Layui深入

1、代码&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>注册页面</title> <style> .container { max-width: 600px; margin: 0 auto; padding: 20px; …

vue的小练习-翻转单词

先将字符串转成数组&#xff0c;用reverse&#xff08;&#xff09;翻转数组&#xff0c;再转成字符串 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevic…

四六级高频词组5

词组 151. be content with&#xff08;be satisfied with&#xff09; 满足于 be content to do sth. 愿意做某事 152. contrary to &#xff08;in opposition to&#xff09; 与…相反 153. on the contrary 相反 154. contrast…with 把…与…相对&#xff08;对照&am…

命令行参数(C语言)

目录 什么是命令行参数 main函数的可执行参数 不传参打印 传参打印 IDE传参 cmd传参 命令行参数的应用&#xff08;文件拷贝&#xff09; 什么是命令行参数 概念&#xff1a;命令行参数指的是在运行可执行文件时提供给程序的额外输入信息。它们通常以字符串形式出现&am…

Leetcode—2697.字典序最小回文串【简单】

2023每日刷题&#xff08;五十八&#xff09; Leetcode—2697.字典序最小回文串 实现代码 char * makeSmallestPalindrome(char * s){int len strlen(s);int left 0, right len - 1;while(left < len / 2) {if(s[left] > s[right]) {s[left] s[right];} else {s[ri…

第三十四周:文献阅读+LSTM学习

目录 摘要 Abstract 文献阅读&#xff1a;综合EMD-LSTM模型在城市排水管网水质预测中的应用 现有问题 提出方法 EMD-LSTM综合模型 研究框架 结论 Long Short-term Memory(长短期记忆) 1. LSTM的结构 2. Multiple-layer LSTM 3.3 LSTM Example 3. GRU LSTM实现PM2…

不再兼容“安卓“,鸿蒙开发与android对比

首先&#xff0c;鸿蒙系统采用了分布式技术&#xff0c;其设计理念是“能用分布式解决的问题就不用单机解决”。这意味着鸿蒙旨在构建一个统一的分布式操作系统&#xff0c;可以支持不同设备之间的交互和通信。 而安卓系统基于Linux内核和Java编程语言构建&#xff0c;属于单机…

使用Nacos作为配置中心

Nacos配置中心简介 首先我们来看一下,微服务架构下关于配置文件的一些问题&#xff1a; 配置文件相对分散。在一个微服务架构下&#xff0c;配置文件会随着微服务的增多变的越来越多&#xff0c;而且分散 在各个微服务中&#xff0c;不好统一配置和管理。配置文件无法区分环境…

GZ029 智能电子产品设计与开发赛题第8套

2023年全国职业院校技能大赛高职组 “GZ029智能电子产品设计与开发”赛项赛卷八 题目&#xff1a;模拟工业传送带物品检测系统的设计与开发 1 竞赛任务 在智能电视机上播放工业传送带传输物品视频&#xff0c;模拟工业传送带物品检测系统&#xff08;以下简称物品检测系统&…

16ASM 汇编基础与Debug使用

目录 硬件运行机制 微机系统硬件组成 计算机系统组成 8086CPU组织结构 DoxBox安装 Debug使用 R命令 D命令 E命令 U命令 T命令 A命令 标志寄存器 常用机器指令 硬件运行机制 下面是一个电子器件二极管&#xff0c;正向加电则通&#xff0c;反向加电则不通 利用二…

西南交通大学【数据结构实验8】

实验内容及要求&#xff1a; 编写控制台应用程序&#xff0c;提供以下菜单项&#xff1a; 插入元素 从键盘输入若干两两互不相同的非0整数&#xff0c;直到输入0时停止。将输入的所有非0整数按输入次序插入二叉排序树(初始时是空树)。 插入某个非0整数时&#xff0c;若该整…

不需要联网的ocr项目

地址 GitHub - plantree/ocr-pwa: A simple PWA for OCR, based on Tesseract. 协议 mit 界面 推荐理由 可以离线使用&#xff0c;隐私安全

JAVA全栈开发 JDBC、反射、设计者模式

一、JDBC 【1】JDBC概述 1.1什么是jdbc Java DataBase Connectivity是一种用于执行SQL语句的Java API&#xff0c;它由一组用Java语言编写的类和接口组成。通过这些类和接口&#xff0c;JDBC把SQL语句发送给不同类型的数据库进行处理并接收处理结果。 1.2jdbc的作用 提供j…

深度探索Linux操作系统 —— 构建桌面环境

系列文章目录 深度探索Linux操作系统 —— 编译过程分析 深度探索Linux操作系统 —— 构建工具链 深度探索Linux操作系统 —— 构建内核 深度探索Linux操作系统 —— 构建initramfs 深度探索Linux操作系统 —— 从内核空间到用户空间 深度探索Linux操作系统 —— 构建根文件系统…

Quartus II + Modelsim 脚本仿真

软件版本&#xff1a;Intel Quartus Prime Design Suite: 23.2 方式参考附件Intel 官方文档&#xff1a;Questa*-Intel FPGA Edition Quick-Start: Intel Quartus Prime Pro Edition 第1步&#xff0c;创建一个ram ip&#xff0c;并形成一个例化的top层ip 第2步&#xff0c;自…

免费图片无损放大:8大平台突破画质极限

之前介绍过图片提高清晰度的工具平台&#xff0c;这次AIGCer介绍下将图片无损放大的几个在线免费的工具平台。图片高清放大是一种处理低分辨率图像的方法&#xff0c;以增加图像的尺寸和细节&#xff0c;使其看起来更大、更清晰。 1.美图设计室 传送门&#xff1a;https://ww…

基于Python+WaveNet+MFCC+Tensorflow智能方言分类—深度学习算法应用(含全部工程源码)(二)

目录 前言引言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理1&#xff09;数据介绍2&#xff09;数据测试3&#xff09;数据处理 相关其它博客工程源代码下载其它资料下载 前言 博主前段时间发布了一篇有关方言识别和分类模型训练的博客&#xff0c;在读者…