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封装】。关注本栏目,将实时更新。

相关推荐
少卿8 分钟前
React Native Vector Icons 安装指南
前端·react native
国家不保护废物13 分钟前
Vue组件通信全攻略:从父子传到事件总线,玩转组件数据流!
前端·vue.js
写不来代码的草莓熊1 小时前
vue前端面试题——记录一次面试当中遇到的题(9)
前端·javascript·vue.js
JinSo1 小时前
pnpm monorepo 联调:告别 --global 参数
前端·github·代码规范
程序员码歌1 小时前
豆包Seedream4.0深度体验:p图美化与文生图创作
android·前端·后端
urhero2 小时前
工作事项管理小工具——HTML版
前端·html·实用工具·工作事项跟踪·任务跟踪小工具·本地小程序
二十雨辰2 小时前
eduAi-智能体创意平台
前端·vue.js
golang学习记2 小时前
从0死磕全栈之Next.js connection() 函数详解:强制动态渲染的正确姿势(附实战案例)
前端
郝学胜-神的一滴2 小时前
Three.js光照技术详解:为3D场景注入灵魂
开发语言·前端·javascript·3d·web3·webgl
m0dw2 小时前
vue懒加载
前端·javascript·vue.js·typescript