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', }; }ConfirmDialog:confirm方法render方法中的弹窗框组件 其中还包含一些其他组件 ConfigProvider Dialog ActionButton
// 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() {}, });
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