React中如何通过函数调用渲染组件 实现类似Antd Modal.info的能力
命令式调用Modal组件实现方案
核心实现原理
这类不需要提前写JSX、直接调用方法就能渲染的组件,核心逻辑是手动创建独立DOM容器 + 直接调用React渲染API挂载组件,完全不需要在业务组件内维护visible状态,也不需要预留组件渲染位置,所有渲染、销毁逻辑都封装在静态方法内部。
完整实现步骤
1. 编写基础受控Modal组件
先实现一个普通的受控Modal组件,接收显示状态、文案、回调等基础props:
// MyModal.tsx import { createRoot } from 'react-dom/client'; import type { ReactNode } from 'react'; // 基础Modal接收的props类型 interface BaseModalProps { visible: boolean; title: string; content: ReactNode; onOk?: () => void; onCancel?: () => void; } const BaseModal = (props: BaseModalProps) => { const { visible, title, content, onOk, onCancel } = props; if (!visible) return null; const handleOk = () => { onOk?.(); onCancel?.(); // 点击确定后默认触发关闭逻辑 }; return ( <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50"> <div className="bg-white rounded-lg w-[480px] p-6"> <h3 className="text-xl font-bold mb-4">{title}</h3> <div className="mb-6 min-h-[40px]">{content}</div> <div className="flex justify-end gap-3"> <button onClick={onCancel} className="px-4 py-2 border rounded hover:bg-gray-50">取消</button> <button onClick={handleOk} className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">确定</button> </div> </div> </div> ); };
2. 封装静态命令式调用方法
在同一个文件内,对外导出封装好的MyModal对象,挂载info等静态方法:
// 调用方法时传入的配置类型 interface ModalConfig { title: string; content: ReactNode; onOk?: () => void; } const MyModal = { info: (config: ModalConfig) => { // 1. 创建临时DOM容器,插入到body下 const container = document.createElement('div'); document.body.appendChild(container); const root = createRoot(container); // 2. 封装销毁逻辑:卸载组件 + 移除临时容器 const destroy = () => { root.unmount(); document.body.removeChild(container); }; // 3. 把基础Modal组件渲染到临时容器中 root.render( <BaseModal visible={true} title={config.title} content={config.content} onOk={config.onOk} onCancel={destroy} /> ); }, // 可按需扩展warning、success、error等方法,仅需调整BaseModal的样式即可 }; export default MyModal;
3. 业务侧使用
和Ant Design的Modal调用方式完全一致:
// 业务组件内调用 import MyModal from './MyModal'; const Item = (props: ItemProps) => { const { itemGroup, items } = props; const showInfo = () => { MyModal.info({ title: '这是一条通知消息', content: ( <div> <p>some messages...some messages...</p> <p>some messages...some messages...</p> </div> ), onOk() { console.log('点击了确定按钮'); }, }); }; return ( <div className="py-6"> <div onClick={showInfo} className="cursor-pointer py-6 px-6 text-3xl font-heading font-bold bg-primary text-white" > <p>{itemGroup.text}</p> </div> {/* 其余业务逻辑省略 */} </div> ); };
兼容React17及更早版本
如果使用React17或更低版本,替换createRoot相关逻辑为旧版渲染API即可:
import ReactDOM from 'react-dom'; // 静态方法内的渲染销毁逻辑替换为: const destroy = () => { ReactDOM.unmountComponentAtNode(container); document.body.removeChild(container); }; ReactDOM.render( <BaseModal visible={true} title={config.title} content={config.content} onOk={config.onOk} onCancel={destroy} />, container );
内容的提问来源于stack exchange,提问作者bitsmyth
相关产品推荐
相关产品推荐

