看了一下,上一篇文章还是1.1号写的,一恍二十多天过来了。轻易写一点react无关的货色吧,这一篇文章次要参考了https://www.cnblogs.com/demod...。
第一步:先写动态模版
src/component/Modal.tsximport React from 'react';import PropTypes from 'prop-types';import './Modal.css'interface ModalProps { onOk: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void; onCancel: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void; title: string; children: PropTypes.ReactElementLike;}export default class Modal extends React.Component<ModalProps> { render() { return ( <div className="modal-container"> <div className="modal-instance"> <div className="modal-title"> {this.props.title} </div> <div className="modal-content"> {this.props.children} </div> <div className="modal-footer"> <button onClick={this.props.onOk} className="button cancel-button">勾销</button> <button onClick={this.props.onCancel} className="submit submit-button">确认</button> </div> </div> </div> ) }}
款式轻易写写:
.modal-container { position: fixed; top: 0; left: 0; height: 100%; width: 100%; background-color:rgba(4,4,4, 0.45);}.modal-instance { position: absolute; top: 50%; left: 50%; background-color: #ffffff; transform: translate(-50%, -50%); border-radius: 3px; border-style: 1px solid #353535;}.modal-title { height: 20px; width: 100%; min-width: 500px; font-size: 16px; font-weight: 500; display: flex; align-items: center;}.modal-content { padding: 5px;}.modal-footer { height: 30px; font-size: 14px; display: flex; align-items: center;}
当初开始调用modal:
class Game extends React.Component<Props, TestState> { constructor(props: Props) { super(props); this.state = { isShowModal: false } } openModal = () => { this.setState({ isShowModal: true }) } render() { const ModalProps = { onOk: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {}, onCancel:(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {}, title: '测试modal', } const { isShowModal } = this.state; return (<> {isShowModal && <Modal {...ModalProps}> <div> {'modal content'} </div> </Modal>} <button onClick={this.openModal}>弹出modal框</button> </> );
当初为止咱们实现了一个简略的动态的modal弹框。当初咱们心愿提供更多的调用形式,比方我心愿应用ModalService.open(template, {onOk: () => {}, onCancel: () => {}})这种api进行调用。那咱们就须要进行封装:
export class ModalService { static open(props: ModalProps) { const modalContainer = document.createElement('div'); document.body.appendChild(modalContainer); function onOk() { props.onOk(); ReactDOM.unmountComponentAtNode(modalContainer); } function onCancel() { props.onCancel(); ReactDOM.unmountComponentAtNode(modalContainer); } ReactDOM.render(<Modal {...props} onOk={onOk} onCancel={onCancel} />, modalContainer); }}
当初咱们来测试一下ModalService.open的调用弹框形式
openModalService = () => { const inputNameChange = (event: React.ChangeEvent<HTMLInputElement>) => { this.setState({ inputName: event.target.value }); } ModalService.open({ onOk: () => { console.log(this.state.inputName); console.log('modal submit ???? by service, and close') }, onCancel: () => { this.setState({ inputName: '' }) console.log('modal cancel ❌ by service, and close') }, title: '这是service关上的', children: (<input type="text" value={this.state.inputName} onChange={inputNameChange} />) }) }
这里其实有个bug,这里的input弹框绑定了value={this.state.inputName} 来绑定,然而其实这个element并没有真正的实现数据绑定,因为他只是创立了一次,并没有和render函数关联所以会呈现,任何对input文本框的输出,都看不到的状况。所以在有输出模版为form的状况下,更好的形式是应用组件调用,在render中应用组件调用的形式。
{isShowModal && <Modal {...ModalProps}> <div> {'modal content'} <input type="text" value={this.state.inputNameStash} onChange={this.inputNameChange} /> </div> </Modal>}
相似这样写。或者modalservice.open的形式关上一个render办法中定义的ref。然而这样如同不太合乎react哲学(so?
最初封装一个链式调用的api吧。
1.先革新modalservice使他返回一个promise
export class ModalService { static open(props: ModalProps) { const modalContainer = document.createElement('div'); document.body.appendChild(modalContainer); return new Promise<void>((resolve, reject) => { function onOk() { props.onOk && props.onOk(); ReactDOM.unmountComponentAtNode(modalContainer); resolve(); } function onCancel() { props.onCancel && props.onCancel(); ReactDOM.unmountComponentAtNode(modalContainer); reject(); } ReactDOM.render(<Modal {...props} onOk={onOk} onCancel={onCancel} />, modalContainer); }) }}
调用形式改为:
openModalServicePromise = async () => { ModalService.open({ title: '期待返回promise进行链式调用', children: '这是期待的promise返回的格局,这样更好用感觉' }).then(() => { console.log('modal 点击了确定✅, and close') }).catch(() => { console.log('modal 点击了勾销????️, and close') }) }
几乎perfect!