基于React实现:弹窗组件与Promise的有机结合
背景
弹窗在现代应用中是最为常见的一种展示信息的形式,二次确认弹窗是其中最为经典的一种。当我们在React,Vue这种数据驱动视图的前端框架中渲染弹窗基本是固定的使用形式。
使用方式:创建新的弹窗组件,在需要弹窗的地方引用并且需要在外层维护弹窗组件的显示/隐藏状态。
这只是庞大项目中一处需要弹窗的地方,如果项目中存在N个需要弹窗的场景,我们都需要将上述步骤重复一次。这会让我们的项目组件变得臃肿冗余。这也是前端开发者比较头疼且常见的问题。那么我们有没有办法解决这种问题呢?
思考
在最近的一次需求中,我尝试去解决这个问题。首先对于二次确认弹窗这种只有在执行某些动作的时候才需要进行展示,其他时间我们应该忽视它的存在。很明显根据传统的做法我们至少需要维护一个组件实例以及一个状态。
是否可以实现只有在执行具体的动作时才调用二次确认弹窗相关的代码呢?就比如命令式调用方法去渲染组件,可以通过ReactDOM.render实现的这种效果。
接着尝试思考第二个问题,对于二次确认弹窗的交互,其实本质上我们只关心用户点击的取消还是确认。对于这种状态二选一的问题,我脑海里面浮现出熟悉的Promise。
于是,我尝试将二次确认弹窗与Promise进行有机结合,实现出命令式二次确认弹窗。当然这种思路可以运用到其他任何类似的场景。
在线演示Live Demo
事实胜于雄辩,这是下方代码实现的真实效果,感兴趣的同学可自行访问看看效果。
Reconfirm Modal DEMO - FE Component Training
代码实现
普通方式实现
-
先通过通用方式实现二次确认弹窗
import { ReactNode } from "react"; import { Button } from "antd"; import "./index.css";interface ModalOption {title: ReactNode;content: ReactNode;okText?: string;cancelText?: string; }interface ReconfirmModalProps {onConfirm: () => void;onClose: () => void;options: ModalOption; }function ReconfirmModal(props: ReconfirmModalProps) {const { onConfirm, onClose, options } = props;const { title, content, okText, cancelText } = options;return (<div className="reconfirm-modal" style={{ zIndex: 10001 }}><div className="reconfirm-modal-body" style={{ width: 400 }}><p className="reconfirm-modal-title">{title}</p><p className="reconfirm-modal-content">{content}</p><div className="reconfirm-modal-footer"><Button size="large" onClick={onClose} block>{cancelText || "取消"}</Button><Button type="primary" size="large" block onClick={onConfirm}>{okText || "确认"}</Button></div></div></div>); }
-
引用二次确认弹窗,进行简单交互
export default function ReconfirmModalPage() {const [visible, setVisible] = useState(false);return (<div><Button danger onClick={() => setVisible(true)}>删除</Button>{visible && (<ReconfirmModalonConfirm={() => {setVisible(false);alert("点击了确认按钮");}}onClose={() => {setVisible(false);alert("点击了取消按钮");}}options={{ title: "删除提示", content: "确认删除吗?" }}/>)}</div>); }
-
看看展示效果
有机结合Promise
我们需要梳理清晰我们的目的,然后再动手进行实现,通过理论指导实践。
首先创建一个方法,调用这个方法时唤醒二次确认弹窗,同时这个方法需要返回二次确认弹窗的交互结果。
通过ReactDOM.render方法将弹窗组件挂在到新创建的root节点上,将Promise的resolve方法传递给弹窗组件的两个按钮事件,此时用户点击按钮时即触发resove方法,Promise状态就从pending状态转移到fulfilled状态。
调用该方法的宿主方法即可得到用户点击二次确认弹窗的点击结果,我们的目的也就达到了。
export const openReconfirmModal = (options: ModalOption) => {return new Promise((resolve) => {const root = document.createElement('div')document.body.appendChild(root)// 移除react组件和DOM节点const removeModal = () => {ReactDOM.unmountComponentAtNode(root)document.body.removeChild(root)}// 点击取消按钮const onClose = () => {removeModal()resolve(false)}// 点击确认按钮const onConfirm = () => {removeModal()resolve(true)}ReactDOM.render(createElement(ReconfirmModal, { onClose, onConfirm, options }), root)})
}
调用二次确认弹窗方法
function ReconfirmModalPage() {const handlePromseReconfirm = async () => {// !!! **直接这么调用就完事儿,简单直接**const res = await openReconfirmModal({title: "删除提示",content: "确认删除吗?",});if (res) {alert("点击了确认按钮");} else {alert("点击了取消按钮");}};return (<Button danger type="primary" onClick={handlePromseReconfirm}>Promise模式删除</Button>);
}
缺点分析
因为我们是通过ReactDOM.render方法渲染的弹窗,这就意味着弹窗组件跟主应用App的状态是隔离的,如果弹窗中用到Redux这种需要上下文Provider能力的工具,就需要在弹窗组件中也初始化一次。但是对于像二次确认弹窗这种简单的纯展示的组件,结合Promise的方式是完全可行的。
总结
日常开发工作中总有一些能够优化的步骤和流程,我们能够多思考一下,转变思路,就能够让我们的代码更加赏心悦目。
原文链接
https://www.levenx.com/article/the-organic-combination-of-pop-up-components-and-promise
个人博客网站,记录更多更全面的内容,
“当你点赞的时候,触碰的不是冰冷的按钮,而是作者那颗感恩的心。”
——鲁迅《非我所言》
相关文章:
![](https://img-blog.csdnimg.cn/75d129e7a4a74ff49a15f16086853f68.gif#pic_center)
基于React实现:弹窗组件与Promise的有机结合
背景 弹窗在现代应用中是最为常见的一种展示信息的形式,二次确认弹窗是其中最为经典的一种。当我们在React,Vue这种数据驱动视图的前端框架中渲染弹窗基本是固定的使用形式。 使用方式:创建新的弹窗组件,在需要弹窗的地方引用并…...
![](https://img-blog.csdnimg.cn/33cae2643d2045488cf10507d08d6f98.png)
docker使用(一)生成,启动,更新(容器暂停,删除,再生成)
docker使用(一) 编写一个 Dockerfile构建镜像构建失败构建成功 运行镜像运行成功 修改代码后再次构建请不要直接进行构建,要将原有的旧容器删除或暂停停止成功删除成功再次构建且构建成功! 要创建一个镜像,你可以按照以…...
![](https://img-blog.csdnimg.cn/afcba34daddc48659a73fe18d0c2a12f.png)
用Qt自制一个小闹钟
小闹钟 功能 当按下启动按钮时,停止按钮可用,启动按钮不可用,闹钟无法设置,无法输入自定义内容 当按下停止按钮时,暂停播报,启动按钮可用,闹钟可以设置,可以输入自定义内容 .pro文…...
![](https://www.ngui.cc/images/no-images.jpg)
Vue2.0/Vue3.0使用xlsx+xlsx-style实现导出Excel文件
一、依赖导入 1、Vue2 Webpack构建的 npm i xlsx npm i xlsx-style npm i file-saver同时修改以下: 解决 Can’t resolve ‘./cptable’ in ‘…’ 的问题,在 vue.config.js 文件中加入该配置 module.exports {externals: {./cptable: var cptable}…...
![](https://img-blog.csdnimg.cn/img_convert/b94a51bd590c2b191793e80f51406adf.png)
【Kafka系列】(一)Kafka入门
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 系列文章地址 Kafka是什么? 一句话概括:「Apache Kafka 是一款开源的消息引擎系统」 什么是消息引擎系统&#…...
![](https://img-blog.csdnimg.cn/0ca8d630b88940d7b06a406d4041ca57.gif)
外包干了2个月,技术退步明显了...
先说一下自己的情况,大专生,19年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年8月份,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...
![](https://img-blog.csdnimg.cn/1f2caad5f1224ffd814a2953d544262a.png)
python实现语音识别
1. 首先安装依赖库 pip install playsound # 该库用于播放音频文件 pip install speech_recognition # 该库用于语音识别 pip install PocketSphinx # 语音识别模块中只有sphinx支持离线的,使用该模块需单独安装 pip install pyttsx3 # 该库用于将文本转换为语音播…...
![](https://img-blog.csdnimg.cn/img_convert/999a7fa69b18b787b0a1f693d0a1f00f.png)
java八股文面试[多线程]——线程的状态
5种状态一般是针对传统的线程状态来说(操作系统层面) 6种状态:Java中给线程准备的 NEW:Thread对象被创建出来了,但是还没有执行start方法。 RUNNABLE:Thread对象调用了start方法,就为RUNNABLE状…...
![](https://www.ngui.cc/images/no-images.jpg)
Go学习[合集]
文章目录 Go学习-Day1Go学习-Day2标识符变量基础语法字符串类型类型转换string和其他基本类型转换其他类型转stringstring转其他类型 指针类型运算符标准IO分支语句 Go学习-Day3循环语句函数声明init函数匿名函数闭包defer Go学习-Day4函数值传递,引用传递常用的函数…...
![](https://img-blog.csdnimg.cn/img_convert/2095e6c508d4246caa0f43e8391507f0.png)
代码随想录算法训练营第42天 | ● 01背包问题,你该了解这些! ● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集
文章目录 前言一、01背包问题,你该了解这些!二、01背包问题,你该了解这些! 滚动数组三、416. 分割等和子集总结 前言 01背包 一、01背包问题,你该了解这些! 确定dp数组以及下标的含义 对于背包问题&#x…...
![](https://img-blog.csdnimg.cn/img_convert/8ba1cfd70369b5b488e70f19055d8b11.png)
解决DNS服务器未响应错误的方法
当你将设备连接到家庭网络或具有互联网接入功能的Wi-Fi热点时,由于各种原因,互联网连接可能无法正常工作。本文中的说明适用于Windows 10、Windows 8和Windows 7。 无法连接到DNS服务器的原因 故障的一类与域名系统有关,域名系统是世界各地互联网提供商使用的分布式名称…...
![](https://img-blog.csdnimg.cn/1d1606a5fea844f98707c8e17dfb7106.png)
SpringBoot的HandlerInterceptor拦截器使用方法
一、创建拦截器 通过实现HandlerInterceptor接口创建自己要使用的拦截器 import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.…...
![](https://www.ngui.cc/images/no-images.jpg)
java 常用 jar 包
1 Lombok 是一个 java 类库,它利用注解方式自动生成 java bean 中 getter、setter、equals 等方法,还能自动生成 logger、toString、hashCode、builder 等 日志相关变量、Object 类方法或设计模式相关的方法,能够让你的 代码更简洁࿰…...
![](https://img-blog.csdnimg.cn/img_convert/b888c20841068f3233de6dfdfd6ba03b.png)
C#面试十问
1:C#中变量类型分为哪两种?它们的区别是什么?2:Class和Struct的区别?3:C#中类的修饰符和类成员的修饰符有哪些?4:面向对象的三个特征(特点)是什么?…...
![](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fassets.leetcode.com%2Fuploads%2F2021%2F01%2F18%2Funiquebstn3.jpg&pos_id=I74nfN8B)
Day 41 动态规划part03 : 343. 整数拆分 96.不同的二叉搜索树
96. 不同的二叉搜索树 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: 输入:n 3 输出:5示例 2: 输入:n 1…...
![](https://img-blog.csdnimg.cn/1e04ed8b485f4932bf0673d90bbbdb2c.png)
四轴飞行器的电池研究(MatlabSimulink仿真)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
![](https://img-blog.csdnimg.cn/img_convert/a4b7035c1f9ddb0cca707a6300b9035f.png)
准备HarmonyOS开发环境
引言 在开始 HarmonyOS 开发之前,需要准备好开发环境。本章将详细指导你如何安装 HarmonyOS SDK、配置开发环境、创建 HarmonyOS 项目。 目录 安装 HarmonyOS SDK 配置开发环境 创建 HarmonyOS 项目 总结 1. 安装 HarmonyOS SDK HarmonyOS SDK 是开发 Harmo…...
![](https://img-blog.csdnimg.cn/06ceee0d2ad14c11a92d94241839e298.jpeg)
Java 面试 - Redis
Redis Redis 是基于键值对的非关系型数据库。Redis 拥有string、hash、list、set、zset等多种数据结构, redis具有惊人的读写性能, 其优秀的持久化机制是的它在断电和机械故障时也不会发生数据丢失, 可以用于热点数据存放, 还提供了键过期、发布订阅、食物、流水线、LUA脚本等多…...
![](https://img-blog.csdnimg.cn/922029c30717493fb93ec7f6f9236b66.png)
【Go 基础篇】Go语言结构体之间的转换与映射
在Go语言中,结构体是一种强大的数据类型,用于定义和组织不同类型的数据字段。当我们处理复杂的数据逻辑时,常常需要在不同的结构体之间进行转换和映射,以便实现数据的转移和处理。本文将深入探讨Go语言中结构体之间的转换和映射技…...
![](https://img-blog.csdnimg.cn/971f3c2631094100ab640eaccacdc8d3.png)
Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)
多线程案例 一、设计模式(单例模式工厂模式)1、单例模式2、工厂模式 二、阻塞式队列1、生产者消费者模型2、阻塞对列在生产者消费者之间的作用3、用标准库阻塞队列实现生产者消费者模型4、模拟实现阻塞队列 三、定时器1、标准库中的定时器2、模拟实现定时…...
![](https://img-blog.csdnimg.cn/img_convert/dbbbd6d03ff6903aebdf56c117e2ca69.png)
将 ordinals 与 比特币智能合约集成 : 第 1 部分
将序数与比特币智能合约集成:第 1 部分 最近,比特币序数在区块链领域引起了广泛关注。 据称,与以太坊 ERC-721 等其他代币标准相比,Ordinals 的一个主要缺点是缺乏对智能合约的支持。 我们展示了如何向 Ordinals 添加智能合约功…...
![](https://img-blog.csdnimg.cn/674bc85291254e91a85812b7910c7248.png)
【USRP】集成化仪器系列1 :信号源,基于labview实现
USRP 信号源 1、设备IP地址:默认为192.168.10.2,请勿 修改,运行阶段无法修改。 2、天线输出端口是TX1,请勿修改。 3、通道:0 对应RF A、1 对应 RF B,运行 阶段无法修改。 4、中心频率:当需要…...
![](https://img-blog.csdnimg.cn/1ad1a35a30a0484d95e3a624dd3da9c5.png)
串行协议——USB驱动[基础]
多年前的学习记录,整理整理。 一、USB协议基础 二、Linux内核USB驱动源码分析 USB中不同类型设备使用的 设备描述符(设备类\设备子类\设备协议) 配置不同,典型的以下几种:1)HID设备: Human Input Device人工输入设备, 如鼠标\键盘\游戏手柄等.2)CDC设备: Communi…...
![](https://img-blog.csdnimg.cn/img_convert/54ca8d1e3f2c46b3b775e7a01f29d0b3.jpeg)
健康舒适的超满意照明体验!SUKER书客SKY护眼台灯测评
健康舒适的超满意照明体验!SUKER书客SKY护眼台灯测评 2022年全国儿童青少年总体近视率为53.6%,其中6岁儿童为14.5%,小学生为36%,初中生为71.6%,高中生为81%,近视已成为当下人们遇到的比较普遍的眼健康问题…...
![](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FZUHCFZqSZztFSTdict6hPGXmO0hboia08xPJlDqrIp0yQM3QQCReM1icLdqOMtKnffyFo1Ze8Qa60hPQOSh8MC3tw%2F640&pos_id=AzNnGziD)
PID 算法
1.1 概述 比例(Proportion)积分(Integral)微分(Differential)控制器(PID控制器或三项控制器)是一种采用反馈的控制回路机制,广泛应用于工业控制系统和需要连续调制控制的…...
![](https://img-blog.csdnimg.cn/c8724980a54d45ccae62df342b7c644e.png)
13.Redis 事务
Redis 事务 redis 事务事务操作multi 开启事务exec 执行事务discard 放弃当前事务watchunwatch redis 事务 Redis 的事务和 MySQL 的事务概念上是类似的。 都是把⼀系列操作绑定成⼀组。 让这⼀组能够批量执⾏。 Redis 的事务和 MySQL 事务的区别: 弱化的原⼦性: 这里指的是 …...
![](https://www.ngui.cc/images/no-images.jpg)
李宏毅机器学习课程笔记(更新ing)
CNN 为什么AlphaGo可以用CNN?棋盘抽象成图片时需要注意什么? 首先图片有两个特点: 1,只观察局部就可以显示某种pattern,比如要得出一个鸟嘴的结论,只需要观察局部图片 2,某种pattern可以出现在图…...
![](https://img-blog.csdnimg.cn/89e2a3e1f2cc4f63bc73bc5b2d3d6df1.png)
SIP mini 对讲终端,带sip热点功能
SV-A10/SV-A10W SIP mini 对讲终端,带sip热点功能 SV-A10/SV-A10W 是专门针对行业用户需求研发的一款 SIP mini 对讲产品,外观小巧,功能 强大,集智能安防、音/视频对讲和广播功能于一体,性价比高。支持壁挂式安装/86…...
![](https://www.ngui.cc/images/no-images.jpg)
PHP中根据出生年月日计算年龄的封装函数
在 PHP 中,你可以使用以下函数来根据出生年月日计算年龄: 封装函数 function calculateAge($birthday) {$currentDate date(Y-m-d);$birthdayDate date(Y-m-d, strtotime($birthday));$age date_diff(date_create($currentDate), date_create($birt…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux巡检脚本
做运维的朋友都知道,大家经常要对一些系统做月度维护或者自查,在这个过程中,如果只是小工作量的查询,进入系统直接输入命令即可。但是如果说要查询的系统很多,每个系统中要查询的项目也很多,那么每次都要一…...
![](http://p02.5ceimg.com/content/cba010c0-c518-eb11-8da9-e4434bdf6706.jpeg)
房地产网站设计/网站建设总结
作者 | 马修.阿拉德 (Matthew Allard ACS)Lesspain软件公司开发的一体化媒体管理软件Kyno更新至1.7版,为这套功能相当丰富的平台增添更多强大功能。主要的新功能• 支持Windows输出ProRes• 更多元数据工作流程• FCPX筛选传统编码媒体文件• 改进转码功能• 改进回…...
最好看的WordPress 音乐播放器/快速seo优化
之前项目中都是使用FusionChart和HighChart,基本都是没有购买商业许可。然后现在开发的系统需要交付给客户使用。所以现在图表控件不能直接使用FusionChart和HighChart,通过对比EChart和D3.js,EChart由百度开发,相关的中文文档和问…...
![](/images/no-images.jpg)
佛山营销手机网站建设/怎样优化网站关键词排名靠前
学习设计模式不光要学习设计模式的思想,还要去深入理解,为什么要用这个设计模式。 如何深入理解?读优秀的框架代码,看别人代码,了解它们的使用场景。 - - - 博主老师(感谢他) 本文先介绍了工厂方…...
![](/images/no-images.jpg)
网页上做网会员网站备案怎么写/品牌营销咨询公司
今天想用ajax和cookie做个自动登录,结果出现很多错误,特在此记录下 一开始我没用cookie是这样的 <input id"log-name" type"text" name"username" placeholder"请输入用户名" οnfοcus"this.placeho…...
![](https://img-blog.csdnimg.cn/img_convert/e6050779021c67b21d707ff8b1c44188.gif)
成都哪里好玩儿的地方推荐/seo综合排名优化
点击上方蓝字关注我们吧~Mybatis中的TypeHandler有两个功能,一个是完成javaType至jdbcType的转换,另外一个是完成jdbcType至javaType的转换。public interface TypeHandler<T> { void setParameter(PreparedStatement ps, int i, T pa…...
![](https://img2018.cnblogs.com/blog/1262452/201809/1262452-20180926232730754-1035966743.png)
网站如何做seo/app001推广平台
引言:最近在弄一个Vue的入门学习用项目,期间有用到 JavaScript 将中文转成拼音这个功能,这可真是为难人。想到了编码,但是没搞明白怎么将编码和拼音字母啥的联系起来。后来上网查询了才知道。声母韵母搭配的拼音(早就忘…...