HOW - 设计一个高度封装性的组件(Modal 弹窗)
一、背景
在以往我们使用一些诸如 antd 或者 elementui 的 Modal 组件时,一般是直接在父组件用一个 visible 变量来控制显示隐藏,并且触发按钮也是在父组件里渲染的。
现在,使用 Ant Design 的 Modal
组件来实现一个通用的弹窗组件。以下是一个示例,展示如何创建一个可复用的弹窗组件。
示例代码
import React, { useState } from "react";
import { Modal, Button } from "antd";
interface CustomModalProps {
title: string; // 弹窗标题
visible: boolean; // 弹窗是否显示
onConfirm?: () => void; // 确定按钮的回调
onCancel?: () => void; // 取消按钮的回调
children?: React.ReactNode; // 弹窗内容
confirmText?: string; // 确定按钮文本
cancelText?: string; // 取消按钮文本
}
const CustomModal: React.FC<CustomModalProps> = ({
title,
visible,
onConfirm,
onCancel,
children,
confirmText = "确定",
cancelText = "取消",
}) => {
return (
<Modal
title={title}
visible={visible}
onOk={onConfirm}
onCancel={onCancel}
okText={confirmText}
cancelText={cancelText}
>
{children}
</Modal>
);
};
// 示例使用
const App: React.FC = () => {
const [isModalVisible, setIsModalVisible] = useState(false);
const showModal = () => setIsModalVisible(true);
const handleConfirm = () => {
console.log("Confirmed!");
setIsModalVisible(false);
};
const handleCancel = () => {
console.log("Cancelled!");
setIsModalVisible(false);
};
return (
<div>
<Button type="primary" onClick={showModal}>
打开弹窗
</Button>
<CustomModal
title="确认操作"
visible={isModalVisible}
onConfirm={handleConfirm}
onCancel={handleCancel}
>
<p>确定要执行此操作吗?</p>
</CustomModal>
</div>
);
};
export default App;
实现细节
-
CustomModal
组件:- 使用
Modal
组件作为基础。 - 提供
title
,visible
,onConfirm
, 和onCancel
等常见参数。 - 支持通过
children
传入自定义内容。
- 使用
-
App
示例:- 使用
useState
控制弹窗的显示与隐藏。 - 点击按钮显示弹窗。
- 点击确定或取消时调用对应的回调函数,并关闭弹窗。
- 使用
-
可扩展性:
- 可以进一步扩展,添加更多自定义的功能,如支持自定义图标、动态表单等内容。
-
样式:
Modal
自带样式支持,使用Ant Design
的主题即可直接适配。- 如果需要额外的样式,可通过
className
或style
属性实现。
二、内置 Trigger
其实,我们可以将触发按钮(Trigger)内置到 Modal
组件中,可以通过传入按钮的配置或直接渲染按钮的方式设计一个更加自包含的 Modal
组件。这样,我们不用实现每一个 Modal 都要在父组件定义一个 visible 变量来控制。
以下是具体实现示例:
示例代码
import React, { useState } from "react";
import { Modal, Button } from "antd";
interface CustomModalProps {
title: string; // 弹窗标题
triggerText?: string; // 触发按钮的文本
triggerType?: "primary" | "default" | "dashed" | "link" | "text"; // 触发按钮的类型
confirmText?: string; // 确定按钮文本
cancelText?: string; // 取消按钮文本
onConfirm?: () => void; // 确定回调
onCancel?: () => void; // 取消回调
children?: React.ReactNode; // 弹窗内容
}
const CustomModal: React.FC<CustomModalProps> = ({
title,
triggerText = "打开弹窗",
triggerType = "primary",
confirmText = "确定",
cancelText = "取消",
onConfirm,
onCancel,
children,
}) => {
const [visible, setVisible] = useState(false);
const handleOpen = () => setVisible(true);
const handleConfirm = () => {
if (onConfirm) onConfirm();
setVisible(false);
};
const handleCancel = () => {
if (onCancel) onCancel();
setVisible(false);
};
return (
<>
{/* 内置触发按钮 */}
<Button type={triggerType} onClick={handleOpen}>
{triggerText}
</Button>
{/* 弹窗 */}
<Modal
title={title}
visible={visible}
onOk={handleConfirm}
onCancel={handleCancel}
okText={confirmText}
cancelText={cancelText}
>
{children}
</Modal>
</>
);
};
// 示例使用
const App: React.FC = () => {
return (
<div>
<CustomModal
title="确认操作"
triggerText="点击打开弹窗"
confirmText="确认"
cancelText="取消"
onConfirm={() => console.log("操作已确认!")}
onCancel={() => console.log("操作已取消!")}
>
<p>这是弹窗的内容。</p>
</CustomModal>
</div>
);
};
export default App;
实现细节
-
CustomModal
组件设计:- 内置一个触发按钮,点击时显示弹窗。
- 触发按钮的文本和类型可以通过
triggerText
和triggerType
进行自定义。 - 点击确定和取消按钮时,支持调用外部传入的回调函数。
-
visible
状态管理:- 使用组件内部的
useState
管理弹窗的显示与隐藏状态。 - 点击触发按钮时打开弹窗;点击确定或取消时关闭弹窗。
- 使用组件内部的
-
扩展性:
- 可以进一步支持更多的触发类型(例如
icon
触发)。 - 如果需要完全自定义触发器,可以通过
renderTrigger
prop,传入一个自定义的触发器组件。
- 可以进一步支持更多的触发类型(例如
-
示例场景:
- 适用于需要在同一个地方定义触发逻辑和弹窗逻辑的场景。
- 简化外部使用者代码,不需要额外管理按钮和弹窗之间的状态。
优化设计(支持自定义触发器)
如果想完全灵活,可以增加 renderTrigger
属性,让用户自定义触发器。
interface CustomModalProps {
renderTrigger?: (handleOpen: () => void) => React.ReactNode; // 自定义触发器
// ... 其他属性
}
const CustomModal: React.FC<CustomModalProps> = ({
renderTrigger,
// ... 其他参数
}) => {
const [visible, setVisible] = useState(false);
const handleOpen = () => setVisible(true);
return (
<>
{renderTrigger ? (
renderTrigger(handleOpen)
) : (
<Button onClick={handleOpen}>默认触发器</Button>
)}
{/* 弹窗 */}
<Modal visible={visible} onCancel={() => setVisible(false)}>{/* 内容 */}</Modal>
</>
);
};
使用示例:
<CustomModal
renderTrigger={(open) => (
<span onClick={open} style={{ color: "blue", cursor: "pointer" }}>
自定义触发器
</span>
)}
>
<p>弹窗内容</p>
</CustomModal>
原文地址:https://blog.csdn.net/weixin_58540586/article/details/144104974
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!