Modal 模态框

模态框。

何时使用

需要用户处理事务,又不希望跳转页面以致打断工作流程时,可以使用 Modal 在当前页面正中打开一个浮层,承载相应的操作。

另外当需要一个简洁的确认框询问用户时,可以使用 Modal.confirm() 等语法糖方法。

请预先在项目页面根节点外包裹 ModalProvider,demo 中 APP 节点外包裹即可省略。

代码演示

基本使用

基本使用。

Modal模态框 - 图1

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const ModalContent = ({ modal }) => {
  5. modal.handleOk(() => {
  6. console.log('do OK');
  7. return false;
  8. });
  9. modal.handleCancel(() => {
  10. console.log('do Cancel');
  11. modal.close();
  12. });
  13. const toggleOkDisabled = React.useCallback(() => {
  14. modal.update({
  15. okProps: { disabled: !modal.props.okProps.disabled },
  16. okText: '保存',
  17. });
  18. }, []);
  19. console.log('modal', modal);
  20. return (
  21. <div>
  22. <p>Some contents...</p>
  23. <p>Some contents...</p>
  24. <p>Some contents...</p>
  25. <Button color="primary" onClick={modal.close}>
  26. custom button for close modal

异步关闭

异步关闭。

Modal模态框 - 图2

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const App = () => {
  5. const Modal = useModal();
  6. const openModal = React.useCallback(() => {
  7. Modal.open({
  8. title: 'Synchronize',
  9. children: (
  10. <div>
  11. <p>Some contents...</p>
  12. <p>Some contents...</p>
  13. <p>Some contents...</p>
  14. </div>
  15. ),
  16. onOk: () =>
  17. new Promise((resolve) => {
  18. setTimeout(() => {
  19. resolve();
  20. }, 1000);
  21. }),
  22. onCancel: () =>
  23. new Promise((resolve, reject) => {
  24. setTimeout(() => {
  25. reject(new Error('error'));
  26. }, 1000);

自定义页脚

自定义页脚。

Modal模态框 - 图3

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const App = () => {
  5. const Modal = useModal();
  6. const openModal = React.useCallback(() => {
  7. const modal = Modal.open({
  8. title: 'Custom Footer',
  9. children: (
  10. <div>
  11. <p>Some contents...</p>
  12. <p>Some contents...</p>
  13. <p>Some contents...</p>
  14. </div>
  15. ),
  16. footer: <Button onClick={closeModal}>关闭</Button>,
  17. });
  18. function closeModal() {
  19. modal.close();
  20. }
  21. }, [Modal]);
  22. const openNoFooter = React.useCallback(() => {
  23. Modal.open({
  24. title: 'No Footer',

多层

多层。

Modal模态框 - 图4

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, Modal, ModalProvider } from 'choerodon-ui/pro';
  4. const { confirm } = Modal;
  5. const App = () => {
  6. const UseModal = useModal();
  7. const openSubModal = React.useCallback(async () => {
  8. return (await confirm('确认关闭?')) === 'ok';
  9. }, [UseModal]);
  10. const openModal = React.useCallback(() => {
  11. UseModal.open({
  12. title: 'Multilayer',
  13. children: (
  14. <div>
  15. <p>Some contents...</p>
  16. <p>Some contents...</p>
  17. <p>Some contents...</p>
  18. </div>
  19. ),
  20. onClose: openSubModal,
  21. });
  22. }, [UseModal, openSubModal]);
  23. return <Button onClick={openModal}>Open</Button>;

自定义坐标

自定义坐标。

Modal模态框 - 图5

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const App = () => {
  5. const Modal = useModal();
  6. const openModal = React.useCallback(() => {
  7. Modal.open({
  8. title: 'No Footer',
  9. children: (
  10. <div>
  11. <p>Some contents...</p>
  12. <p>Some contents...</p>
  13. <p>Some contents...</p>
  14. </div>
  15. ),
  16. style: {
  17. left: 100,
  18. top: 200,
  19. },
  20. });
  21. }, [Modal]);
  22. return <Button onClick={openModal}>Open</Button>;
  23. };
  24. ReactDOM.render(

关闭按钮

关闭按钮。

Modal模态框 - 图6

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const App = () => {
  5. const Modal = useModal();
  6. const openModal = React.useCallback(() => {
  7. Modal.open({
  8. title: 'Close button',
  9. children: (
  10. <div>
  11. <p>Some contents...</p>
  12. <p>Some contents...</p>
  13. <p>Some contents...</p>
  14. </div>
  15. ),
  16. closable: true,
  17. });
  18. }, [Modal]);
  19. return <Button onClick={openModal}>Open</Button>;
  20. };
  21. ReactDOM.render(
  22. <ModalProvider>
  23. <App />
  24. </ModalProvider>,

确认框

确认框。

Modal模态框 - 图7

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { Modal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. function doConfirm() {
  5. Modal.confirm({
  6. title: 'Confirm',
  7. children: (
  8. <div>
  9. <p>Some contents...</p>
  10. <p>Some contents...</p>
  11. <p>Some contents...</p>
  12. </div>
  13. ),
  14. }).then((button) => {
  15. Modal.info(`Click ${button}`);
  16. });
  17. }
  18. function info() {
  19. Modal.info({
  20. title: 'This is title',
  21. children: '您的订单已经提交!',
  22. });
  23. }
  24. function success() {
  25. Modal.success('订单提交成功!');

全屏显示

全屏显示。

Modal模态框 - 图8

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const App = () => {
  5. const Modal = useModal();
  6. const openModal = React.useCallback(() => {
  7. Modal.open({
  8. title: 'Full screen',
  9. children: (
  10. <div>
  11. <p>Some contents...</p>
  12. <p>Some contents...</p>
  13. <p>Some contents...</p>
  14. </div>
  15. ),
  16. fullScreen: true,
  17. });
  18. }, [Modal]);
  19. return <Button onClick={openModal}>Open</Button>;
  20. };
  21. ReactDOM.render(
  22. <ModalProvider>
  23. <App />
  24. </ModalProvider>,

多层抽屉

通过设定多个 drawer 类型的弹出框形成多层抽屉,可指定弹出层宽度,弹出动画。

Modal模态框 - 图9

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const App = () => {
  5. const Modal = useModal();
  6. const openSubModal2 = React.useCallback(() => {
  7. return new Promise((resolve) => {
  8. Modal.open({
  9. title: 'Sub Mode 2',
  10. size: 'large',
  11. drawer: true,
  12. drawerTransitionName: 'slide-left',
  13. children: (
  14. <div>
  15. <p>Open Sub Modal2...</p>
  16. <p>Open Sub Modal2...</p>
  17. </div>
  18. ),
  19. onOk: resolve,
  20. });
  21. });
  22. }, [Modal]);
  23. const openSubModal1 = React.useCallback(() => {
  24. return new Promise((resolve) => {
  25. Modal.open({

更新渲染

更新渲染。

Modal模态框 - 图10

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const ModalContent = ({ modal }) => {
  5. modal.handleOk(() => {
  6. console.log('do OK');
  7. return false;
  8. });
  9. modal.handleCancel(() => {
  10. console.log('do Cancel');
  11. modal.close();
  12. });
  13. const handleUpdate = React.useCallback(() => {
  14. modal.update({
  15. title: 'update',
  16. children: (
  17. <div>
  18. <p>update contents...</p>
  19. </div>
  20. ),
  21. okText: '保存',
  22. cancelText: '退出',
  23. onOk: () => modal.close(),
  24. });
  25. }, [modal]);
  26. return (

destroyAll

destroyAll 销毁所有弹出的Modal框。

Modal模态框 - 图11

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { Modal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. function destroyAll() {
  5. Modal.destroyAll();
  6. }
  7. function destroyConfirm() {
  8. for (let i = 0; i < 4; i++) {
  9. setTimeout(() => {
  10. Modal.confirm({
  11. title: 'Confirm',
  12. children: <Button onClick={destroyAll}>Click to destroy all</Button>,
  13. });
  14. }, i * 600);
  15. }
  16. }
  17. ReactDOM.render(
  18. <Button onClick={destroyConfirm}>Open</Button>,
  19. document.getElementById('container'),
  20. );

自定义遮罩样式

自定义遮罩样式

Modal模态框 - 图12

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. import { useModal, Button, ModalProvider } from 'choerodon-ui/pro';
  4. const maskStyle = {
  5. backgroundColor: 'rgb(0, 193, 255,.3)',
  6. };
  7. const App = () => {
  8. const Modal = useModal();
  9. const openModal = React.useCallback(
  10. (mask = true) => {
  11. Modal.open({
  12. title: 'Customized mask',
  13. children: (
  14. <div>
  15. <p>Some contents...</p>
  16. <p>Some contents...</p>
  17. <p>Some contents...</p>
  18. </div>
  19. ),
  20. okText: '确定',
  21. maskStyle,
  22. mask,
  23. maskClassName: 'mask-class-name',
  24. });
  25. },

API

Modal

参数说明类型默认值
key唯一键, 当 destroyOnClose 为 false 时,必须指定 key。为了避免与其他 modal 的 key 重复,可通过 Modal.key()来获取唯一 key。string
title标题ReactNode
closable显示右上角关闭按钮booleanfalse
movable可移动, drawer 无法移动booleantrue
fullScreen全屏显示booleanfalse
maskClosable点击蒙层是否允许关闭booleanfalse
mask是否显示蒙层booleantrue
maskStyle蒙层样式CSSProperties
maskClassName蒙层自定义样式名string
keyboardClosable按 esc 键是否允许关闭booleantrue
destroyOnClose关闭时是否销毁booleantrue
footer底部内容ReactNode 或 (okBtn, cancelBtn) => ReactNode
okText确认按钮文字ReactNode确定
cancelText取消按钮文字ReactNode取消
onClose关闭时回调,返回false Promise.resolve(false)Promise.reject()不会关闭, 其他自动关闭() => Promise<boolean>
onOk点击确定回调,返回false Promise.resolve(false)Promise.reject()不会关闭, 其他自动关闭() => Promise<boolean>
onCancel点击取消回调,返回false Promise.resolve(false)Promise.reject()不会关闭, 其他自动关闭() => Promise<boolean>
afterClose关闭后回调() => void
drawer抽屉模式booleanfalse
drawerTransitionName抽屉模式使用的动画string‘slide-right’
okCancel同时显示 ok 和 cancel 按钮,false 的时候只显示 ok 按钮booleantrue
okFirstok 按钮是否排在第一个booleantrue
okPropsok 按钮属性object
cancelPropscancel 按钮属性object

ModalProvider > v0.8.50

  • 使用 Modal 前,需要在页面根节点外包裹 ModalProvider。如果路由切换时要清空所有 Modal,需要在 ModalProvider 传入 location,如下所示。
  • 如果 Modal 要获取 React Context,请在对应的 Context.Provider 子节点外包裹 ModalProvider,并使用 ModalProvider 提供的 injectModal 或 useModal 来代替 Modal.open。
  1. import { ModalProvider } from 'choerodon-ui/pro';
  2. import { withRouter } from 'react-router';
  3. @withRouter
  4. class App extends React.Component {
  5. render() {
  6. const { location } = this.props;
  7. return (
  8. <ModalProvider location={location}>
  9. <Main />
  10. </ModalProvider>
  11. );
  12. }
  13. }
  14. render(<App />, mountNode);

ModalContent <= v0.8.50

  • 使用 Modal 前,需要在页面 Root 内插入 ModalContainer。如果路由切换时要清空所有 Modal,需要在 ModalContiner 传入 location,如下所示。
  • 如果 Modal 要获取 React Context,请将 ModalContainer 至于 Context.Provider 之下。
  • 为了避免多个 ModalContainer 之间 Context 错乱, ModalContainer 务必作为第一个子元素使用。
  1. import { ModalContainer } from 'choerodon-ui/pro';
  2. import { withRouter } from 'react-router';
  3. @withRouter
  4. class App extends React.Component {
  5. render() {
  6. const { location } = this.props;
  7. return (
  8. <div>
  9. <ModalContainer location={location} />
  10. <Main />
  11. </div>
  12. );
  13. }
  14. }
  15. render(<App />, mountNode);

Modal.open

Modal.open()返回一个对象,该对象具有如下方法:

名称说明参数
close(destroy)关闭destroy - 是否销毁
open()打开
update(props)更新

props.modal

Modal 会向内部组件注入 modal 对象,该对象具有如下属性与方法:

名称说明参数
handleOk(callback)注册响应 ok 按钮的钩子,返回值为 false 将阻止关闭callback - 钩子
handleCancel(callback)注册响应 cancel 按钮的钩子,返回值为 false 将阻止关闭callback - 钩子
close(destroy)关闭destroy - 是否销毁
update(props)更新
propsmodal 的 props