• React如何命令式调用自定义的Antd-Modal组件


    目录结构

    ├─RiskModal
    │      index.js	//将riskModal与show等方法结合起来并导出
    │      riskModal.js	//自定义Modal
    │      riskModal.less
    │      show.js	//命令时调用
    
    • 1
    • 2
    • 3
    • 4
    • 5

    riskModal.js

    import { Modal } from 'antd-mobile';
    
    const RiskModal = ({
                         visible,
                         onClose,
    						...
                       }) => {
    	...
      return (
        <Modal visible={visible} onClose={onClose}>
    	...自定义样式
    	</Modal>)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    以前多数情况下,都是在父函数式组件中作为组件去调用,每次都需要定义visible状态并传入。

    show.js

    import { renderImperatively } from '@/utils/render-imperatively';
    
    export const show = (props) => {
      return renderImperatively(
        <RiskModal
          {...props}
        />,
      );
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    render-imperatively.js 命令式渲染组件
    import React, { useEffect, useImperativeHandle, useRef, useState } from 'react';
    import { renderToBody } from '@/utils/renderToBody';
    import { isFunction } from 'lodash';
    
    export function renderImperatively(element) {
      //Wrapper组件单独维护一个visible状态,React.forwardRef主要是用来暴露close方法给父组件调用
      const Wrapper = React.forwardRef((_, ref) => {
        const [visible, setVisible] = useState(false);
        const closedRef = useRef(false);
        //初始化组件时修改展示状态
        useEffect(() => {
          if (!closedRef.current) {
            setVisible(true);
          } else {
            afterClose();
          }
        }, []);
    
        function onClose() {
          closedRef.current = true;
          setVisible(false);
          if (isFunction(element?.props?.onClose))
            element.props.onClose();
        }
    
        function afterClose() {
          unmount();
          if (isFunction(element?.props?.onClose))
            element.props.onClose();
        }
    
        useImperativeHandle(ref, () => ({
          close: onClose,
        }));
    
        return React.cloneElement(element, {
          ...element.props,
          visible,
          onClose,
          afterClose,
        });
      });
      const wrapperRef = React.createRef();
      //将新复制的组件挂载到body上,重点其实是这个
      const unmount = renderToBody(<Wrapper ref={wrapperRef} />);
    
      function close() {
        if (isFunction(wrapperRef?.current?.close))
          wrapperRef.current.close();
      }
    
      return {
        close,
      };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    renderToBody.js 将组件挂载到body
    import ReactDOM from 'react-dom';
    
    export const renderToBody = (element) => {
      const container = document.createElement('div');
      document.body.appendChild(container);
    
      function unmount() {
        const unmountResult = ReactDOM.unmountComponentAtNode(container);
        if (unmountResult && container.parentNode) {
          container.parentNode.removeChild(container);
        }
      }
    
      ReactDOM.render(element, container);
      return unmount;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    index.js

    import RiskModal from './riskModal';
    import { show } from './show';
    import { attachPropertiesToComponent } from '@/utils/attach-properties-to-component';
    
    export default attachPropertiesToComponent(RiskModal, {
      show,
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    attach-properties-to-component.js 给组件增加属性
    export const attachPropertiesToComponent = (component, properties) => {
      const ret = component;
      for (const key in properties) {
        if (properties.hasOwnProperty(key)) {
          ret[key] = properties[key];
        }
      }
      return ret;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    命令式调用

    import RiskModal from '@/components/RiskModal';
    
    RiskModal.show({
          type,
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    pipenv创建虚拟环境+创建django程序
    矩阵的概念
    webpack搭建vue脚手架
    RabbitMQ官方案例学习记录
    JVM监控:JMX组件与底层原理
    SpringBoot MongoDB操作封装
    Linux下编译cpp_redis
    【入门-03】时钟系统
    Python-Django 项目模块-自带表单Form的使用(十一)
    弱监督学习
  • 原文地址:https://blog.csdn.net/ice_cream__/article/details/133746517