看了一下,上一篇文章还是1.1号写的,一恍二十多天过去了。随便写一点react有关的东西吧,这一篇文章主要参考了https://www.cnblogs.com/demod...。
第一步:先写静态模版
src/component/Modal.tsx
import 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!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。