React+TS前台项目实战(八)-- 全局常用组件模态框Modal封装

文章目录

  • 前言
  • Modal模态框组件
    • [1. 功能分析](#1. 功能分析)
    • [2. 代码+详细注释说明](#2. 代码+详细注释说明)
    • [3. 使用方式](#3. 使用方式)
    • [4. 效果展示](#4. 效果展示)
  • 总结

前言

今天这篇主要讲项目中经常会用到的模态框Modal组件封装。模态框可用在很多地方,比如弹窗Dialog使用、消息提示Message使用等都可以在外层套上Modal组件,下一讲会讲到Dialog组件的封装,就是基于模态框进行开发的。


Modal模态框组件

1. 功能分析

(1)用于在页面上显示一个弹出窗口,由遮罩层和主体部分组成。遮罩层覆盖整个屏幕,用于阻止点击穿透到下层内容。主体部分包含传入的 children,即模态框的内容。

(2)组件使用 useEffect 钩子来监听 Esc 键的按下,并在按下时关闭模态框

(3)OutsideClickHandler 组件用于检测模态框外部的点击,并调用 onClose 回调函数关闭模态框。

2. 代码+详细注释说明

c 复制代码
// @/components/Modal/index.tsx
import React, { useEffect } from "react";
import classNames from "classnames";
import OutsideClickHandler from "react-outside-click-handler";
import styles from "./index.module.scss";

type Props = {
  // 是否显示模态框
  show: boolean;
  // 模态框内容
  children: React.ReactNode;
  // 关闭模态框时的回调函数
  onClose: () => void;
  // 自定义样式类名
  className?: string;
};

export default (props: Props) => {
  const { show, children, onClose, className } = props;
  // 监听 Esc 键关闭模态框
  useEffect(() => {
    const handlerKeyDown = (event: KeyboardEvent) => {
      if (event.keyCode === 27) {
        onClose();
      }
      window.addEventListener("keydown", handlerKeyDown);
      return () => {
        window.removeEventListener("keydown", handlerKeyDown);
      };
    };
  }, [onClose]);
  // 当模态框不可见时,返回 null,不渲染模态框组件
  if (!show) {
    return null;
  }
  return (
    <>
      {/* 模态框遮罩层 */}
      <div className={styles.modalMask}>
        {/* 外部点击区域 */}
        <OutsideClickHandler onOutsideClick={onClose}>
          {/* 模态框主体 */}
          <div className={classNames(styles.modalWrap, className)}>{children}</div>
        </OutsideClickHandler>
      </div>
    </>
  );
};
------------------------------------------------------------------------------
// @/components/Modal/index.module.scss
.modalMask {
  position: fixed;
  top: 0;
  bottom: 0;
  inset-inline-end: 0;
  inset-inline-start: 0;
  z-index: 1000;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.45);
  .modalWrap {
    position: absolute;
    z-index: 10;
    top: 200px;
    left: 50%;
    transform: translateX(-50%);
    background-color: #ffffff;
    border-radius: 4px;
    max-width: 90%;
    box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);

    @media screen and (max-width: 750px) {
      max-width: calc(100vw - 32px);
    }
  }
}

3. 使用方式

c 复制代码
// 引入组件
import Modal from "@/pages/components/commonDialog";
// 使用
<Modal show={show} onClose={onClose}>
  <div style={{ padding: "20px" }}>这是一个模态框</div>
</Modal>

4. 效果展示


总结

下一篇讲【全局常用组件弹窗Dialog封装】。关注本栏目,将实时更新。

相关推荐
梨子同志几秒前
手动实现 JavaScript 的 call、apply 和 bind 方法
前端·javascript
梨子同志2 分钟前
ES6 let 和 const
前端·javascript
用户5806139393002 分钟前
超越 console.log():前端调试的 10 个神级技巧
前端
却尘3 分钟前
当全世界都在用 Rust 重写一切时,Prisma 却选择了反方向
前端·数据库·orm
这是个栗子3 分钟前
前端开发者常用网站
前端
前端小白佬19 分钟前
【JS】防抖(debounce)和节流(throttle)
前端·面试
GIS之路21 分钟前
OpenLayers 从后端服务加载 GeoJSON 数据
前端
开始编程吧29 分钟前
【HarmonyOS5】仓颉编程:当多范式统一成为智能时代的「通用语言」
前端
PasserbyX38 分钟前
ES6 WeakMap 生效的证明: FinalizationRegistry
前端·javascript
努力学习的小刘41 分钟前
如何使用react-router实现动态路由
前端·javascript