相似於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> ) }
「積跬步、行千里」—— 持續更新中~,喜歡的話留下個贊和關注哦!