antd Modal 组件细节点

  1. 设置 destroyOnClose属性,关闭时销毁组件
    1. 这样重新进入Modal时就会再次挂载组件
    2. 否则会有缓存上一次的值 Bug
  2. 4x Modal内的表单,点击冒泡,会触发外层的 onClick
    1. 解决Modal外层包裹个 div
    2. <div onClick={e => e.stopPropagation()}><Modal/></div>
    3. antd 5x Modal 没有这个问题
  3. 弹窗表单 ModalForm,只做弹窗的显示和隐藏,单一职责原则
  4. 隐藏 footer 默认底部的,确定取消按钮,取消 onCancel和 onOk,
    1. 省去 okButtonProps属性传递 ```jsx

和 Form 一起配合使用时,设置 destroyOnClose 也不会在 Modal 关闭时销毁表单字段数据, 需要设置

confirmLoading={true} onButtonProps={{loading: true}}

  1. <a name="zG4e6"></a>
  2. ## ProModal
  3. ```jsx
  4. import {
  5. useState,
  6. cloneElement,
  7. isValidElement,
  8. forwardRef,
  9. useImperativeHandle
  10. } from 'react';
  11. import {
  12. number, bool, string, func, node, object, oneOfType
  13. } from 'prop-types';
  14. import { Modal, Button } from 'antd';
  15. function RenderAction({element, onClick, buttonProps}) {
  16. if(isValidElement(element)) {
  17. return cloneElement(element, {
  18. onClick,
  19. });
  20. }
  21. if(buttonProps) {
  22. return (
  23. <Button
  24. type={'primary'}
  25. {...buttonProps}
  26. onClick={onClick}
  27. />
  28. )
  29. }
  30. return null;
  31. }
  32. function BaseModal(props, ref) {
  33. const { children, element, text, buttonProps, ...rest } = props;
  34. const [visible, setVisible] = useState(false);
  35. useImperativeHandle(ref, () => ({
  36. onShow,
  37. onClose,
  38. }));
  39. function onShow() {
  40. setVisible(true)
  41. }
  42. function onClose() {
  43. setVisible(false);
  44. }
  45. return (
  46. <>
  47. <RenderAction
  48. element={element}
  49. buttonProps={buttonProps}
  50. onClick={onShow}
  51. />
  52. {
  53. visible && (
  54. <Modal
  55. {...rest}
  56. visible={visible}
  57. // destroyOnClose
  58. // maskClosable={false} 点击遮罩不关闭
  59. // closable={false} 不显示标题右侧 x
  60. >
  61. {children}
  62. </Modal>
  63. )
  64. }
  65. </>
  66. );
  67. }
  68. const BaseModalRef = forwardRef(BaseModal);
  69. BaseModalRef.propTypes = {
  70. title: node,
  71. width: oneOfType([number, string]),
  72. text: string,
  73. onOk: func,
  74. onCancel: func,
  75. closable: bool,
  76. destroyOnClose: bool,
  77. buttonProps: object,
  78. };
  79. BaseModalRef.defaultProps = {
  80. width: 560,
  81. text: '新建',
  82. closable: false,
  83. destroyOnClose: true,
  84. }
  85. export default BaseModalRef;

使用 ProModal

image.png
image.png

  1. import React, { useRef } from 'react';
  2. import { func } from 'prop-types';
  3. import { TagsOutlined } from '@ant-design/icons';
  4. import { BaseModal } from '@/components'
  5. BrandedAsTag.propTypes = {
  6. onChange: func,
  7. };
  8. function BrandedAsTag({onChange}) {
  9. const modalRef = useRef(null)
  10. function onCancel() {
  11. modalRef.current?.onClose();
  12. }
  13. function onOk() {
  14. }
  15. return (
  16. <BaseModal
  17. ref={modalRef}
  18. title='会员打标签'
  19. buttonProps={{
  20. type: 'link',
  21. size: 'small',
  22. icon: <TagsOutlined />,
  23. children: '打标签'
  24. }}
  25. onCancel={onCancel}
  26. onOk={onOk}
  27. >
  28. 123123
  29. </BaseModal>
  30. );
  31. }
  32. export default BrandedAsTag;

Modal 自定义 footer

  1. footer: [
  2. <Button
  3. block
  4. onClick={onCancel}
  5. key='cancel'
  6. >
  7. 取消
  8. </Button>,
  9. <Button
  10. block
  11. className="ml16"
  12. type="primary"
  13. onClick={onSubmit}
  14. key='submit'
  15. >
  16. {okText}
  17. </Button>
  18. ],