• react-demo项目:自定义实现一个弹框Dialog组件


    弹框组件的基本项目都会使用到,这次自定义实现一个简单的弹框组件。
    显示标题,内容以及底部
    主要用到的点:https://zh-hans.reactjs.org/docs/portals.html

    Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

    ReactDOM.createPortal(child, container)
    
    • 1

    第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

    代码如下

    src\components\Dialog\index.jsx文件

    
    import React, { forwardRef, useEffect, useMemo, useState } from 'react'
    import ReactDOM from 'react-dom';
    import style from './index.css';
    
    function Dialog(props) {
      const { visible = false, title, children, footer } = props;
    
      useEffect(() => {
        // 查找dialog节点
        let dom = document.getElementById('dialog');
    
        // 存在即删除
        (!visible && dom) && document.body.removeChild(dom);
    
        // 设置属性id
        let divDialog = document.createElement('div');
        divDialog.setAttribute('id', 'dialog');
        divDialog.setAttribute('class', 'dialog');
        document.body.append(divDialog)
    
      }, [])
    
      return (
        <>
          {
            (document.getElementById('dialog') && visible) && ReactDOM.createPortal(
              <div className={style['H-Dialog-overview']}>
                <div className={style['H-Dialog-inner']}>
                  <div className={style['dialog-header']}>
                    <h3>{title}</h3>
    
                  </div>
                  <div className={style['dialog-body']}>
                    {children}
                  </div>
                  <div className={style['dialog-footer']}>
                    {footer}
                  </div>
    
                </div>
              </div>, document.getElementById('dialog'))
          }
        </>
      )
    
    }
    
    export default Dialog
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    src\components\Dialog\index.css文件

    .dialog {
    
    }
    .H-Dialog-overview {
      /* 设置弹框背景以及无法点击页面*/
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      z-index: 1001;
      background-color: rgba(0, 0,0,0.6);
      display: flex;
      justify-content: center;
      
    }
    .H-Dialog-inner {
      height: 200px;
      width: 400px;
      background-color: #fff;
      position: absolute;
      top: 20vh;
      padding: 20px;
    }
    .dialog-header {
      margin-bottom: 10px;
    }
    .dialog-body{
    
    }
    .dialog-footer {
      position: absolute;
      bottom: 20px;
      margin: auto;
      text-align: center;
      
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    组件使用

    src\pages\Home\index.jsx文件

    import { Button } from 'antd';
    import React, { useState } from 'react';
    import Dialog from '../../components/Dialog/index.jsx'
    
    export default function Home() {
    
      const [visible, setVisible] = useState(false)
      return (
        <div className="H-Home">
          <h2>home</h2>
          <h4>ui</h4>
          <div>
            <Button type='primary' onClick={() => {
              setVisible(true)
            }}>计算</Button>
          </div>
    
          <Dialog
            visible={visible}
            title={"这是一个弹窗"}
            footer={
              <>
                <Button onClick={() => {
                  setVisible(false)
                }}>确定</Button>
              </>
            }
          >
            <div>
              hello
            </div>
          </Dialog>
        </div>
      )
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    效果图

    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    2023年全球市场一次性外科引流系统总体规模、主要生产商、主要地区、产品和应用细分研究报告
    机器学习DAYX:线性回归与逻辑回归
    国内常用的代理ip形式数据中心代理ip和静态住宅代理IP有什么区别
    List - Watch 通讯机制
    【华为OD机试真题 python】猜密码 【2022 Q4 | 200分】
    使用kubekey的all-in-one安装K8S1.24及KubeSphere3.3
    ubuntu20.4部署java web环境
    Python获取Window系统注册表安装的软件,再卸载软件
    线索化二叉树的实现(思路分析) [数据结构与算法]
    今日AI:GPT-4.5意外曝光可能6月发布、UP主借AI识别情绪播放量186万、全球首个AI程序员诞生
  • 原文地址:https://blog.csdn.net/weixin_40119412/article/details/128200572