编程语言
首页 > 编程语言> > antd-design源码学习系列-Modal

antd-design源码学习系列-Modal

作者:互联网

 

在日常的项目开发过程中,基本上很少自己写组件,都是使用现成的antd组件库,用起来确实比较方便。

知其然更要知其所以然!

这边来看看Modal实现的源码分析~

 

第一层: index.tsx(给modal上增加一些方法,Modal.info, Modal.success........)

返回confirm函数的调用,confirm函数接受withInfo(props)作为入参

props:是我们的调用props,包括一些title,content

const Modal = OriginModal as ModalType; // 引入OriginModal增加方法
Modal.info = function infoFn(props: ModalFuncProps) {
  return confirm(withInfo(props)); //
};

Modal.success = function successFn(props: ModalFuncProps) {
  return confirm(withSuccess(props));
};

Modal.error = function errorFn(props: ModalFuncProps) {
  return confirm(withError(props));
};

Modal.warning = modalWarn;

 confirm方法:

//confirm方法主要进行一些组件配置config的渲染,显示出弹出框

// 主要是render()方法的调用

export default function confirm(config: ModalFuncProps) {
  const container = document.createDocumentFragment();
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
  let currentConfig = { ...config, close, visible: true } as any;

  function destroy(...args: any[]) {
  }

  function render({ okText, cancelText, prefixCls: customizePrefixCls, ...props }: any) {
    /**
     * https://github.com/ant-design/ant-design/issues/23623
     *
     * Sync render blocks React event. Let's make this async.
     */
    setTimeout(() => {
      reactRender(
        <ConfirmDialog
          {...props}
          prefixCls={prefixCls}
          rootPrefixCls={rootPrefixCls}
          iconPrefixCls={iconPrefixCls}
          okText={okText || (props.okCancel ? runtimeLocale.okText : runtimeLocale.justOkText)}
          cancelText={cancelText || runtimeLocale.cancelText}
        />,
        container,
      );
    });
  }

  function close(...args: any[]) {
    currentConfig = {
      ...currentConfig,
      visible: false,
      afterClose: () => {
        if (typeof config.afterClose === 'function') {
          config.afterClose();
        }

        destroy.apply(this, args);
      },
    };
    render(currentConfig);
  }

  function update(configUpdate: ConfigUpdate) {
  }

  render(currentConfig);

  destroyFns.push(close);

  return {
    destroy: close,
    update,
  };
}

withInfo方法:

// 主要对传入的props进行封装,以及默认值赋值

export function withInfo(props: ModalFuncProps): ModalFuncProps {
  return {
    icon: <InfoCircleOutlined />,
    okCancel: false,
    ...props,
    type: 'info',
  };
}
// Modal.info使用时
Modal.info({ title: 'This is a notification message', content: ( <div> <p>some messages...some messages...</p> <p>some messages...some messages...</p> </div> ), onOk() {}, });
ConfirmDialog:confirm方法render方法中的弹窗框组件 其中还包含一些其他组件   ConfigProvider   Dialog     ActionButton
const ConfirmDialog = (props: ConfirmDialogProps) => {
 ...
  return (
    <ConfigProvider prefixCls={rootPrefixCls} iconPrefixCls={iconPrefixCls} direction={direction}>
      <Dialog // import Dialog from 'rc-dialog';(从另一个第三方库引入)
        ...
      >
        <div className={`${contentPrefixCls}-body-wrapper`}>
          <div className={`${contentPrefixCls}-body`}>
            {icon}
            {props.title === undefined ? null : (
              <span className={`${contentPrefixCls}-title`}>{props.title}</span>
            )}
            <div className={`${contentPrefixCls}-content`}>{props.content}</div>
          </div>
          <div className={`${contentPrefixCls}-btns`}>
            {cancelButton} 
<ActionButton
              type={okType}
              actionFn={onOk}
              close={close}
              autoFocus={autoFocusButton === 'ok'}
              buttonProps={okButtonProps}
              prefixCls={`${rootPrefixCls}-btn`}
            >
              {okText}
            </ActionButton>
          </div>
        </div>
      </Dialog>
    </ConfigProvider>
  );
}

所以整个流程就是:函数调用时,将传入的props进行封装初始化(withInfo),然后通过confirm()调用,打开弹出框

 

上面讲的是一些快捷方法的调用,这边说一下常规的Modal调用过程

<Modal
          title="Basic Modal"
          visible={this.state.visible} // 弹窗显示
          onOk={this.handleOk}
          onCancel={this.handleCancel}
        >
          <p>Some contents...</p> // children - 内容显示
          <p>Some contents...</p>
          <p>Some contents...</p>
        </Modal>

Modal:

  const Modal: React.FC<ModalProps> = props => {
..........//有一些默认的函数及ui
return (
    <Dialog
      {...restProps}
      getContainer={
        getContainer === undefined ? (getContextPopupContainer as getContainerFunc) : getContainer
      }
      prefixCls={prefixCls}
      wrapClassName={wrapClassNameExtended}
      footer={footer === undefined ? defaultFooter : footer}
      visible={visible}
      mousePosition={mousePosition}
      onClose={handleCancel}
      closeIcon={closeIconToRender}
      focusTriggerAfterClose={focusTriggerAfterClose}
      transitionName={getTransitionName(rootPrefixCls, 'zoom', props.transitionName)}
      maskTransitionName={getTransitionName(rootPrefixCls, 'fade', props.maskTransitionName)}
    />
  );
}

 

这里主要是返回Dialog组件,还是要去扒Dialog源码

Dialog源码:

  return (
    <div
      className={classNames(`${prefixCls}-root`, rootClassName)}
      {...pickAttrs(props, { data: true })}
    >
      <Mask
        prefixCls={prefixCls}
        visible={mask && visible}
..........
      />
      <div
        tabIndex={-1}
  ...........
      >
        <Content
          {...props}
          onm ouseDown={onContentMouseDown}
          onm ouseUp={onContentMouseUp}
          ref={contentRef}
..........
        />
      </div>
    </div>
  );

Mask:(下面代码)

Content:(代码差不多,都是对于外部组件的引入。。。。。)

    <CSSMotion //import CSSMotion from 'rc-motion';
// 扒不动了,还是引入了其他组件
      key="mask"
      visible={visible}
.......
    >
      {({ className: motionClassName, style: motionStyle }) => (
        <div
......
          {...maskProps}
        />
      )}
    </CSSMotion>

就这样吧,其实整个流程还是清晰的,就是通过一些props的传入,来进行弹窗框的外观的一些初始显示,没有什么复杂的逻辑,但是这里确实写的高阶组件的层层嵌套。

后面附上别人封装写的就很简单:

// 这个是写的可拖动的Modal,原理简洁一目了然,优秀优秀!

  render() {
    const { children, title, wrapStyles, titleStyles, visible, onCancel } = this.props;
// 这个是实现可拖动的Modal
    return (
      <div ref={this.dragBoxRef} className={`dragModal ${visible ? 'opened' : ''}`} style={wrapStyles}>
        <div draggable className="topBar" onDragStart={this.handleDragStart} onDragEnd={this.handleDragEnd}>
          <div className="title" style={titleStyles}>
            <span>{title || '标题11'}</span>
            <div className="closeBtn" onClick={onCancel}>
              <CloseOutlined />
            </div>
          </div>
        </div>
// 传入的内容
        {React.Children.map(children, child => child && React.cloneElement(child as any))}
      </div>
    );
  }

 

标签:function,...,return,confirm,源码,design,Modal,props
来源: https://www.cnblogs.com/best-mll/p/16371883.html