本文同时发布于掘金,地址:https://juejin.im/post/6844903858523602957
本文译自:30-seconds-of-react 。React 30 秒速学: 精选有用的 React 片段,30-seconds-of-react 的中文版本,已全部完成翻译、上线,地址:30-seconds-of-react-zh_CN-umi 。
模态组件
可通过事件控制的模态组件。
要使用该组件,只导入一次Modal
,然后通过将一个布尔值传递给isVisible
属性来显示它。
- 使用对象解构来设置模态组件的某些属性的默认值。
- 定义
keydownHandler
方法,用于处理所有键盘事件,可以根据你的需要使用它来调度动作(例如,当按下Esc时关闭模态)。
*使用React.useEffect()
hook来添加或删除keydown
事件监听器,它调用keydownHandler
。
*使用isVisible
道具来确定是否应该显示模态。
*使用CSS来设置和定位模态组件。
样式:
.modal {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right:0;
width: 100%;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.25);
animation-name: appear;
animation-duration: 300ms;
}
.modal-dialog{
width: 100%;
max-width: 550px;
background: white;
position: relative;
margin: 0 20px;
max-height: calc(100vh - 40px);
text-align: left;
display: flex;
flex-direction: column;
overflow:hidden;
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.4s;
animation-name: slide-in;
animation-duration: 0.5s;
}
.modal-header,.modal-footer{
display: flex;
align-items: center;
padding: 1rem;
}
.modal-header{
border-bottom: 1px solid #dbdbdb;
justify-content: space-between;
}
.modal-footer{
border-top: 1px solid #dbdbdb;
justify-content: flex-end;
}
.modal-close{
cursor: pointer;
padding: 1rem;
margin: -1rem -1rem -1rem auto;
}
.modal-body{
overflow: auto;
}
.modal-content{
padding: 1rem;
}
@keyframes appear {
from {opacity: 0;}
to {opacity: 1;}
}
@keyframes slide-in {
from {transform: translateY(-150px);}
to { transform: translateY(0);}
}
组件:
import React from "react";
import styles from "./Modal.css";
function Modal({ isVisible = false, title, content, footer, onClose }) {
React.useEffect(() => {
// 监听事件
document.addEventListener("keydown", keydownHandler);
// 取消监听
return () => document.removeEventListener("keydown", keydownHandler);
});
function keydownHandler({ key }) {
// esc 键,关闭模态框
switch (key) {
case "Escape":
onClose();
break;
default:
}
}
// 控制模态框显示
return !isVisible ? null : (
<div className={styles["modal"]} onClick={onClose}>
<div
className={styles["modal-dialog"]}
onClick={e => e.stopPropagation()}
>
<div className={styles["modal-header"]}>
<h3 className={styles["modal-title"]}>{title}</h3>
<span className={styles["modal-close"]} onClick={onClose}>
×
</span>
</div>
<div className={styles["modal-body"]}>
<div className={styles["modal-content"]}>{content}</div>
</div>
{footer && <div className={styles["modal-footer"]}>{footer}</div>}
</div>
</div>
);
}
例子
// 将组件添加到 render 函数
function App() {
const [isModal, setModal] = React.useState(false);
return (
<React.Fragment>
{/* 按钮显示模态框 */}
<button onClick={() => setModal(true)}>显示模态框</button>
<Modal
isVisible={isModal}
title="标题"
content={<p>正文</p>}
footer={<button onClick={() => setModal(false)}>关闭模态框</button>}
onClose={() => setModal(false)}
/>
</React.Fragment>
);
}
export default function() {
return <App />;
}