基于React实现:弹窗组件与Promise的有机结合

背景

弹窗在现代应用中是最为常见的一种展示信息的形式,二次确认弹窗是其中最为经典的一种。当我们在React,Vue这种数据驱动视图的前端框架中渲染弹窗基本是固定的使用形式。

使用方式:创建新的弹窗组件,在需要弹窗的地方引用并且需要在外层维护弹窗组件的显示/隐藏状态。

这只是庞大项目中一处需要弹窗的地方,如果项目中存在N个需要弹窗的场景,我们都需要将上述步骤重复一次。这会让我们的项目组件变得臃肿冗余。这也是前端开发者比较头疼且常见的问题。那么我们有没有办法解决这种问题呢?

思考

在最近的一次需求中,我尝试去解决这个问题。首先对于二次确认弹窗这种只有在执行某些动作的时候才需要进行展示,其他时间我们应该忽视它的存在。很明显根据传统的做法我们至少需要维护一个组件实例以及一个状态。

是否可以实现只有在执行具体的动作时才调用二次确认弹窗相关的代码呢?就比如命令式调用方法去渲染组件,可以通过ReactDOM.render实现的这种效果。

接着尝试思考第二个问题,对于二次确认弹窗的交互,其实本质上我们只关心用户点击的取消还是确认。对于这种状态二选一的问题,我脑海里面浮现出熟悉的Promise。

于是,我尝试将二次确认弹窗与Promise进行有机结合,实现出命令式二次确认弹窗。当然这种思路可以运用到其他任何类似的场景。

在线演示Live Demo

事实胜于雄辩,这是下方代码实现的真实效果,感兴趣的同学可自行访问看看效果。

Reconfirm Modal DEMO - FE Component Training

代码实现

普通方式实现

  1. 先通过通用方式实现二次确认弹窗

    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>);
    }
    
  2. 引用二次确认弹窗,进行简单交互

    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>);
    }
    
  3. 看看展示效果

    二次确认弹窗演示图

有机结合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

个人博客网站,记录更多更全面的内容,

“当你点赞的时候,触碰的不是冰冷的按钮,而是作者那颗感恩的心。”

——鲁迅《非我所言》

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

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

相关文章

【系统设计系列】 回顾可扩展性

系统设计系列初衷 System Design Primer&#xff1a; 英文文档 GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards. 中文版&#xff1a; https://github.com/donnemart…

【React】React学习:从初级到高级(三)

3 状态管理 随着应用不断变大&#xff0c;应该更有意识的去关注应用状态如何组织&#xff0c;以及数据如何在组件之间流动。冗余或重复的状态往往是缺陷的根源。 3.1 用State响应输入 3.1.1 声明式地考虑UI 总体步骤如下&#xff1a; 定位组件中不同的视图状态 确定是什么…

C++零碎记录(四)

6. 深拷贝与浅拷贝 ① 浅拷贝&#xff1a;简单的赋值拷贝操作。 ② 深拷贝&#xff1a;在堆区重新申请空间&#xff0c;进行拷贝操作。 ③ 浅拷贝&#xff0c;如下图所示&#xff0c;带来的问题就是堆区的内存重复释放。 ④ 深拷贝&#xff0c;如下图所示&#xff0c;在堆区…

深度学习-4-二维目标检测-YOLOv5源码测试与训练

本文采用的YOLOv5源码是ultralytics发行版3.1 YOLOv5源码测试与训练 1.Anaconda环境配置 1.1安装Anaconda Anaconda 是一个用于科学计算的 Python 发行版&#xff0c;支持 Linux, Mac, Windows, 包含了众多流行的科学计算、数据分析的 Python 包。 官方网址下载安装包&…

pdf怎么编辑文字?了解一下这几种编辑方法

pdf怎么编辑文字&#xff1f;PDF文件的普及使得它成为了一个重要的文件格式。然而&#xff0c;由于PDF文件的特性&#xff0c;它们不可直接编辑&#xff0c;这就使得PDF文件的修改变得比较麻烦。但是&#xff0c;不用担心&#xff0c;接下来这篇文章就给大家介绍几种编辑pdf文字…

go语言基本操作---三

变量的内存和变量的地址 指针是一个代表着某个内存地址的值。这个内存地址往往是在内存中存储的另一个变量的值的起始位置。Go语言对指针的支持介于java语言和C/C语言之间&#xff0c;它即没有想Java语言那样取消了代码对指针的直接操作的能力&#xff0c;也避免了C/C语言中由…

Redis面试题(笔记)

目录 1.缓存穿透 2.缓存击穿 3.缓存雪崩 小结 4.缓存-双写一致性 5.缓存-持久性 6.缓存-数据过期策略 7.缓存-数据淘汰策略 数据淘汰策略-使用建议 数据淘汰策略总结 8.redis分布式锁 setnx redission 主从一致性 9.主从复制、主从同步 10.哨兵模式 服务状态监…

最快1个月录用!9月SCI/SSCI/EI刊源表已更新!

2023年9月SCI/SSCI/EI期刊目录更新 2023年9月份刊源表已更新&#xff01;计算机、医学、工程、环境、SSCI均有新增期刊&#xff0c;1区(TOP)&#xff0c;最快1个月录用&#xff0c;好刊版面紧俏&#xff0c;切莫错失机会&#xff01; 01 计算机领域 02 医学与制药领域 03 工…

桌面应用小程序,一种创新的跨端开发方案

Qt Group在提及2023年有桌面端应用程序开发热门趋势时&#xff0c;曾经提及三点&#xff1a; 关注用户体验&#xff1a;无论您是为桌面端、移动端&#xff0c;还是为两者一起开发应用程序&#xff0c;有一点是可以确定的&#xff1a;随着市场竞争日益激烈&#xff0c;对产品的期…

Python爬取天气数据并进行分析与预测

随着全球气候的不断变化&#xff0c;对于天气数据的获取、分析和预测显得越来越重要。本文将介绍如何使用Python编写一个简单而强大的天气数据爬虫&#xff0c;并结合相关库实现对历史和当前天气数据进行分析以及未来趋势预测。 1 、数据源选择 选择可靠丰富的公开API或网站作…

电子科大软件系统架构设计——面向对象建模基础

文章目录 面向对象建模基础UML建模语言UML模型图用例图活动图类图顺序图通信图状态机图构件图部署图包图对象图组合结构图扩展图交互概览图时间图 BPMN建模语言业务建模定义模型元素流对象活动事件网关 流数据人工制品泳池和泳道 建模案例订单采购流程建模电商系统订货业务流程…

搭建最简单的SpringBoot项目

1、创建maven项目 2、引入父pom <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.15</version> </parent> 3、引入springboot-web依赖 <dependency…

React【React是什么?、创建项目 、React组件化、 JSX语法、条件渲染、列表渲染、事件处理】(一)

文章目录 React是什么&#xff1f; 为什么要学习React React开发前准备 创建React项目 React项目结构简介 React组件化 初识JSX 渲染JSX描述的页面 JSX语法 JSX的Class与Style属性 JSX生成的React元素 条件渲染&#xff08;一&#xff09; 条件渲染 &#xff0…

系统架构技能之设计模式-工厂模式

一、开篇 本文主要是讲述设计模式中最经典的创建型模式-工厂模式&#xff0c;本文将会从以下几点对工厂模式进行阐述。 本文将会从上面的四个方面进行详细的讲解和说明&#xff0c;当然会的朋友可以之处我的不足之处&#xff0c;不会的朋友也请我们能够相互学习讨论。 二、摘…

Java后端开发面试题——企业场景篇

单点登录这块怎么实现的 单点登录的英文名叫做&#xff1a;Single Sign On&#xff08;简称SSO&#xff09;,只需要登录一次&#xff0c;就可以访问所有信任的应用系统 JWT解决单点登录 用户访问其他系统&#xff0c;会在网关判断token是否有效 如果token无效则会返回401&am…

C#循环定时上传数据,失败重传解决方案,数据库标识

有些时候我们需要定时的上传一些数据库的数据&#xff0c;在数据不完整的情况下可能上传失败&#xff0c;上传失败后我们需要定时在重新上传失败的数据&#xff0c;该怎么合理的制定解决方案呢&#xff1f;下面一起看一下&#xff1a; 当然本篇文章只是提供一个思路&#xff0…

SAP-PP:基础概念笔记-5(物料主数据的MRP1~4视图)

文章目录 前言一、MRP1视图Base Unit of Measure&#xff08;UoM&#xff09;MRP 组采购组ABC 指示器Plant-Specific Material Status 特定的工厂物料状态MRP 类型 MRP TypeMRP 类型 MRP TypeMaster Production Scheduling(MPS) 主生产计划基于消耗的计划(CBP)再订货点Reorder-…

uni-app点击复制指定内容(点击复制)

官方api uni.setClipboardData(OBJECT) uni.setClipboardData({data: 要被复制的内容,success: function () {console.log(success);} });

Liquid UI和Fiori的区别

主要围绕以下几个方面就Liquid UI和Firor来进行比较&#xff1a; 开发周期开发成本稳定性和支援性平台架构 影响Firor决策的因素&#xff1a; 复杂的编程过程&#xff0c;Fiori对开发人员要求高&#xff0c;开发难度大&#xff0c;而Liquid UI让开发人员不需要懂SAP后端&…

yolov5运行过程遇到的小问题(随时更新)

1.关于git的问题 解决办法&#xff1a;插入下面代码 import os os.environ["GIT_PYTHON_REFRESH"] "quiet"2.页面太小无法完成操作 解决办法: 如果不好使再考虑降低Batch_Size大小或者调整虚拟内存可用硬盘空间大小&#xff01;&#xff08;调整虚拟内存…