相似于antd实现的modal组件,首先基本结构分析:node
modal-mask
遮罩层modal-warp
内容包装层modal
主体内容层,包含:title
、content
、footer
、close-btn
实现功能目标:react
<Modal {...props}>一些内容</Modal>
、Modal.confirm({...props})
footer
和close-btn
的显示与否,单击是否可关闭<div className="lwh-pirate-modal"> <div className="lwh-modal-mask"/> // 遮罩层须要实现全屏遮罩 // 内容层高度可自定义 <div className={`lwh-modal-warp ${wrapClassName}`} style={{width}}> // 右上角关闭按钮 <div className="lwh-modal-close"><span>+</span></div>} // 主内容 <div className="lwh-modal" style={{width,...style}}> <div className="lwh-modal-content"> //title标题 <div className="lwh-modal-header"> <div className="lwh-modal-title">{title}</div> </div> //body用户输入内容 <div className="lwh-modal-body"> {children} </div> // footer底部按钮 <div className="lwh-modal-footer"> <div> <Button type={okType}>{okText}</Button> <Button type={cancelType}>{cancelText}</Button> </div> </div> </div> </div> </div> </div>
遮罩层全屏覆盖编程
position: fixed
定位top: 0; right: 0; bottom: 0; left: 0; z-index: 1000;
内容层segmentfault
position: fixed
定位(modal-warp层)warp层的布局大小考虑
modal
层的单击,虽然单击的仍是warp层);modal
层:及设置warp层的大小恰好为其内容modal
,这样就不会覆盖所有mask层,可是,后期对传入设置是否显示mask层的功能有所影响(由于warp层不全屏,若是mask设置不显示,会致使用户能够操做到底下主内容),可考虑mask的显隐经过visibility: hidden
控制.const Modal = ({ visible=false, style, width= 520, zIndex=1000, centered=false, title='title', footer, wrapClassName='', okText='肯定', okType='primary', cancelText='取消', cancelType='default', closable= true, onOk=() => {}, onCancel=() => {}, mask=true, maskClosable= true, children='Basic body' }) => { return ( visible ? ReactDOM.createPortal(<div>....</div>,document.querySelector('body')) : null ) }
Modal
的显隐由外部控制,内部不控制;ReactDOM.createPortal(child,container)
挂载至bodyimport React,{ PureComponent } from 'react'; import { Modal,Button } from 'lwh_react'; export default class baseModal extends PureComponent { state = { visible: false } showModal = () => { this.setState({ visible: true }) } onCancel = () => { console.log('cancel') this.setState({ visible: false }) } onOk = () => { console.log('ok') this.setState({ visible: false }) } render() { const { visible } = this.state; return ( <div> 简单基本用法: <Button onClick={this.showModal}>modal</Button> <Modal visible={visible} onCancel={this.onCancel} onOk={this.onOk}> <div>modal提示内容</div> </Modal> </div> ) } }
Modal.method()
的攻克如何实现相似antd
中modal.method的方法调用弹窗形式(且调用后返回一个引用包含{update, destroy}
可控制弹窗):跨域
Modal.info({...})
Modal.success({...})
Modal.error({...})
Modal.warning({...})
Modal.confirm({...})
method()
是Modal的方法即先给组件Modal
增长对应方法,返回一个对象;性能优化
method(props)
方法中将其方法参数做为组件Modal的props传入,并render(Modal);{update, destroy}
基本代码以下:['confirm','info','success','error','warning'].forEach(item => { // eslint-disable-next-line react/no-multi-comp Modal[item] = ({ ...props}) => { let div = document.createElement('div'); let currentConfig = Object.assign({}, props); document.body.appendChild(div); // 使用高阶组件剔除Method()调用形式不可配置的props和默认值 const FunModal = HOCModal(Modal); // 关闭 const destroy = () => { const unmountResult = ReactDOM.unmountComponentAtNode(div); if (unmountResult && div.parentNode) { div.parentNode.removeChild(div); } } const render = (config) => { //name传入调用的方法名,用于区分使用不一样footer和Icon ReactDOM.render(<FunModal destroy={destroy} name={item} {...config} />, div); } // 更新 const update = (newConfig) => { currentConfig = Object.assign({}, currentConfig,newConfig); render(currentConfig); } render(currentConfig); return { destroy: destroy, update: update } } });
Modal.method()
调用形式可以使用的配置props与<Modal></Modal>
中的配置项和默认值有所不一样;Modal.confirm({})
中不可配置footer
;Modal.info({})
的footer
底部默认应该为一个button
,且默认值为我知道了
;Modal.method()
不须要传递visible
,而<Modal></Modal>
形式须要传入;Modal.method()
中没有children,而使用content做为内容的传递,因此须要适配下;HocModal
对传给Modal
的props进行部分剔除和默认值修改const HOCModal = (Component) => { //剔除出visible,footer,closable,使其不可配,赋予永久默认值 return ({ visible, footer, closable, okText='知道了', okType='primary', onOk=() => {}, onCancel=() => {}, maskClosable= false, content='Basic body', name, destroy, ...props }) => { // 修改onOk方法传入关闭Modal方法destroy(); const onOk_1 = () => { onOk(); destroy(); } // 修改onCancel方法传入关闭Modal方法destroy(); const onCancel_1 = () => { onCancel(); destroy(); } // Modal底部footer固定使用这里为默认值,且不可自定义footer,若是调用的是confirm返回undefined走Modal的默认配置,其余则只显示一个OK、button // eslint-disable-next-line react/no-multi-comp const Footer = () => ( name == 'confirm' ? undefined : <Button onClick={onOk_1} type={okType}>{okText}</Button> ) return ( <Component okText={okText} closable={false} maskClosable={maskClosable} onOk={onOk_1} footer={Footer()} onCancel={onCancel_1} children={content} okType={okType} visible {...props} /> ) } }
const ModalConfirm = () => { const onInfo = () => { Modal.info({ title: 'Info', content: ( <div> <p>some messages...some messages...</p> <p>some messages...some messages...</p> </div> ), onOk() {} }); } const showDeleteConfirm = () => { const modal = Modal.confirm({ title: '你肯定须要删除该项么?', content: '一些删除提示内容', okText: '删除', okType: 'danger', cancelText: '取消', onOk() { console.log('OK'); }, onCancel() { console.log('Cancel'); } }); console.log(modal); } return ( <div> <Button onClick={showDeleteConfirm} type="dashed">删除</Button> <Button onClick={onInfo} type="primary">info</Button> </div> ) }
“积跬步、行千里”—— 持续更新中~,喜欢的话留下个赞和关注哦!