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

news2024/11/27 15:39:55

背景

弹窗在现代应用中是最为常见的一种展示信息的形式,二次确认弹窗是其中最为经典的一种。当我们在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 && (
            <ReconfirmModal
              onConfirm={() => {
                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.coloradmin.cn/o/976444.html

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

相关文章

百叶帘系统内置于玻璃内,分为手动和电动两种控制方式

百叶帘系统是一种在餐厅包厢隔断墙中常见的控制窗帘或遮光帘的方式。这种系统通常分为手动和电动两种控制方式&#xff0c;具体选择取决于您的需求和预算。 1. 手动控制&#xff1a;手动控制是传统的方式&#xff0c;通过手动操作绳子或杆来打开或关闭百叶帘。这是一种经济实惠…

力扣刷题49 字母 异位词分组

目录 题目描述代码实现基本实现优化代码 基础知识回溯集合 参考 题目描述 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 示例 1: 输入: strs [“eat”, “tea”…

19|返璞归真:王维佛系建议,万事不如吃好睡好

好诗相伴&#xff0c;千金不换。你好&#xff0c;我是天博。 今天我们的主题仍然是“见自己”。其实&#xff0c;诗词里并不是只有诗情画意的春花秋月&#xff0c;也充满了实实在在的人间烟火。这些现实的生活对我们平常人来说&#xff0c;往往比春花秋月更有借鉴意义。我们今…

基于Java+SpringBoot+Vue前后端分离在线考试系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

蝶形运算法

蝶形运算法是一种基于FFT&#xff08;Fast Fourier Transform&#xff09;算法的计算方法&#xff0c;其基本思想是将长度为N的DFT分解成若干个长度为N/2的DFT计算&#xff0c;并通过不断的合并操作得到最终的结果。该算法也称为“蝴蝶算法”&#xff0c;因为它的计算过程中需要…

未加载Qt6Core.pdb

编译代码发现未加载.pdb。 问题是Qt6的bin目录下也没有.pdb文件啊&#xff1f; 有两种方法&#xff0c;一是把Qt路径放到环境变量下&#xff0c;这样系统就能找到Qt6需要的依赖项。 二是在生成目录下找到编译好的.exe文件&#xff0c;然后调用windeployqt.exe为其生成依赖项&…

通用策略06丨横截面因子在期货中的应用(2)

量化策略开发&#xff0c;高质量社群&#xff0c;交易思路分享等相关内容 大家好&#xff0c;今天为大家带来2023年度通用系列的收官之作——再议横截面因子。 在通用05策略中&#xff0c;我们以一种很简单的框架和复现方式&#xff0c;为大家展示了横截面因子在期货中的运用展…

5. 本地方法接口和本地方法栈

5.1. 什么是本地方法&#xff1f; 简单地讲&#xff0c;一个Native Method是一个Java调用非Java代码的接囗。一个Native Method是这样一个Java方法&#xff1a;该方法的实现由非Java语言实现&#xff0c;比如C。这个特征并非Java所特有&#xff0c;很多其它的编程语言都有这一…

云贝餐饮连锁独立版 v2.7.9+公众号+小程序端+全插件(免授权前端线传)安装教程

云贝餐饮连锁版主要基于目前比较流行小程序生态下的自助点单系统&#xff0c;一款非常不错的餐饮外卖小程序。播播资源测试云贝餐饮连锁独立版 v2.7.9该版本与上一版一样永久授权版&#xff0c;增加了小程序前端线传功能&#xff08;通过其他第三方上传&#xff09;&#xff0c…

jdk17下netty导致堆内存疯涨原因排查 | 京东云技术团队

背景&#xff1a; 介绍 天网风控灵玑系统是基于内存计算实现的高吞吐低延迟在线计算服务&#xff0c;提供滑动或滚动窗口内的count、distinctCout、max、min、avg、sum、std及区间分布类的在线统计计算服务。客户端和服务端底层通过netty直接进行tcp通信&#xff0c;且服务端…

JS判断对象是否发生变化,常用于监听页面表单是否修改并给出保存提示

本文主要封装方法&#xff0c;实现用户离开表单编辑页面时弹出提示框&#xff0c;若表单数据发生变化&#xff0c;则提示用户是否保存当前页面的信息&#xff0c;如图&#xff1a; 封装方法&#xff1a; /*** 比较俩个对象之间的差异&#xff0c;项目中多处用到监听表单数据是…

配电室能耗数据采集系统

随着社会的快速发展&#xff0c;能源消耗逐年增加&#xff0c;能源问题已成为制约我国经济社会发展的瓶颈。在此背景下&#xff0c;节能减排、绿色发展成为国家战略&#xff0c;而配电室作为电力系统的重要组成部分&#xff0c;其能耗管理对整个电力系统的能效有着举足轻重的影…

SQL sever中表数据管理

目录 一、插入数据&#xff1a; 二、更新数据&#xff1a; 三、删除数据&#xff1a; 四、清空数据&#xff1a; 4.1使用DELETE语句&#xff1a; 4.2 使用TRUNCATE TABLE语句&#xff1a; 4.3区别&#xff1a; 4.3.1DELETE FROM&#xff1a; 4.3.2TRUNCATE TABLE&am…

正文—态路小课堂丨光模块安装与拆卸的小指南

点击蓝字 | 关注我们 TARLUZ态路 光模块通常由非常精密的光学元件组成&#xff0c;对于光信号的接收和发射非常敏感。静电和光口污染对光模块信号传输有着很大的影响。静电会导致光模块器件的性能降低、寿命缩短&#xff0c;可能会造成不可逆的损坏。光口污染会导致光信号的衰…

“海葵”强势来袭,台风天如何做好防涝排水工作?

中央气象台9月4日06时发布台风黄色预警&#xff1a;今年第11号台风“海葵”&#xff08;HAIKUI&#xff09;的中心已于昨天&#xff08;9月3日&#xff09;晚上7点50分前后移入台湾海峡南部海面。 预计&#xff0c;“海葵”将以每小时10公里左右的速度向西偏北方向移动&#xf…

提振印度市场?iPhone15首发之一,富士康工厂将提前生产iPhone15

根据金融时报的报道&#xff0c;苹果公司计划将印度作为其新款 iPhone 15 的首发市场之一。以往的经验显示&#xff0c;印度市场通常会比其他市场延迟一个月左右才能上市&#xff0c;但今年情况将发生变化。据报道&#xff0c;位于印度东南部城市金奈的富士康工厂计划在9月中旬…

浅析安防视频监控平台EasyCVR视频融合平台接入大量设备后是如何维持负载均衡的

安防视频监控平台EasyCVR视频融合平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。视频汇聚融合管理平台EasyCVR既具备…

qemu/kvm学习笔记

qemu/kvm架构 cpu虚拟化的示例 Reference: kvmtest.c [LWN.net] 主要步骤&#xff1a; QEMU通过/dev/kvm设备文件发起KVM_CREATE_VM ioctl&#xff0c;请求KVM创建一个虚拟机。KVM创建虚拟机相应的结构体&#xff0c;并为QEMU返回一个虚拟机文件描述符QEMU通过虚拟机文件描述…

【每日一题】54. 螺旋矩阵

54. 螺旋矩阵 - 力扣&#xff08;LeetCode&#xff09; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5…

电脑内存不足怎么办?分享4个释放空间小妙招!

“我的电脑好像也没有保存什么很大的文件&#xff0c;为什么总会显示电脑内存不足呀&#xff1f;现在电脑非常的卡&#xff0c;有什么好用的方法可以快速清理电脑内存吗&#xff1f;希望大家给我出出主意&#xff01;” 我们在使用电脑时&#xff0c;可能电脑悄悄地保存了很多的…