ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

antd-design源码学习系列-Modal

2022-06-13 18:31:33  阅读:277  来源: 互联网

标签:function ... return confirm 源码 design Modal props


 

在日常的项目开发过程中,基本上很少自己写组件,都是使用现成的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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有