Modal, PopUP, Toast, ToolTip 等这些都属于弹框。平时我们使用弹框一般有两种方式:一种是通过函数形式弹出,另一种是组件形式弹框。
下面我分别对两种弹出方式写了2个 Demo,如果有可以优化的地方,请多多指点。。。
函数形式弹出
// mask.js
import React from 'react';
import {Button} from 'antd';
import ReactDOM from 'react-dom';
const styles = {
mask: {
position: 'fixed',
top: 0,
right: 0,
left: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.65)',
height: '100%',
zIndex: 1000,
},
modalWrap: {
position: 'fixed',
top: 0,
right: 0,
left: 0,
bottom: 0,
zIndex: 1000,
},
modal: {
fontSize: 14,
padding: 20,
width: 520,
height: 200,
margin: '100px auto 0',
backgroundColor: '#fff',
borderRadius: 4,
overflow: 'hidden',
textAlign: 'center',
},
btnGroup: {
padding: 10,
textAlign: 'right'
}
};
export default {
dom: null, //被append的元素
success ({title, content, onOk, onCancel}) {
this.close();
this.dom = document.createElement('div');
// JSX代码
const JSXdom = (
<div>
<div style={styles.mask} />
<div style={styles.modalWrap}>
<div style={styles.modal}>
<h2>{title}</h2>
<p>{content}</p>
<div style={styles.btnGroup}>
<Button onClick={() => this.onCancel(onCancel)}>取消</Button>
<Button type="primary" onClick={() => this.onOk(onOk)}>确定</Button>
</div>
</div>
</div>
</div>
);
ReactDOM.render(JSXdom, this.dom);
document.body.appendChild(this.dom);
},
onCancel (onCancel) {
(onCancel instanceof Function) && onCancel();
this.close();
},
onOk (onOk) {
(onOk instanceof Function) && onOk();
this.close();
},
close () {
this.dom && this.dom.remove();
}
}
怎么使用?调用 mask.js 里的 success 方法。
import Mask from './mask';
export default class Home extends React.Component {
showModal () {
Mask.success({
title: 'Modal',
content: 'Hello World !',
onCancel: () => {
console.log('Cancel');
},
onOk: () => {
console.log('Ok');
}
})
}
render () {
return (
<button onClick={this.showModal}>JS显示弹框</button>
)
}
}
组件形式弹框
import React, {Component} from 'react';
import {Button} from 'antd';
import ReactDOM from 'react-dom';
const styles = {
mask: {
position: 'fixed',
top: 0,
right: 0,
left: 0,
bottom: 0,
backgroundColor: 'rgba(0, 0, 0, 0.65)',
height: '100%',
zIndex: 1000,
},
modalWrap: {
position: 'fixed',
top: 0,
right: 0,
left: 0,
bottom: 0,
zIndex: 1000,
},
modal: {
fontSize: 14,
padding: 20,
width: 520,
height: 200,
margin: '100px auto 0',
backgroundColor: '#fff',
borderRadius: 4,
overflow: 'hidden',
textAlign: 'center',
},
btnGroup: {
padding: 10,
textAlign: 'right'
}
};
export default class MaskEle extends Component {
constructor (props) {
super(props);
this.modal = null;
}
componentDidMount () {
this.modal = document.createElement('div');
this.props.visible && document.body.appendChild(this.modal);
this._renderLayer();
}
componentDidUpdate () {
if (this.props.visible) {
document.body.appendChild(this.modal);
this._renderLayer();
} else {
this.modal.parentNode.removeChild(this.modal);
}
}
onCancel = () => {
const { onCancel } = this.props;
(onCancel instanceof Function) && onCancel();
}
onOk = () => {
const { onOk } = this.props;
(onOk instanceof Function) && onOk();
}
// 渲染模态框内容
_renderLayer () {
const {title, content} = this.props;
let JSXdom = (
<div>
<div style={styles.mask} />
<div style={styles.modalWrap}>
<div style={styles.modal}>
<h2>{title}</h2>
<p>{content}</p>
<div style={styles.btnGroup}>
<Button onClick={this.onCancel}>取消</Button>
<Button type="primary" onClick={this.onOk}>确定</Button>
</div>
</div>
</div>
</div>
);
ReactDOM.render(JSXdom, this.modal);
}
render () {
return null;
}
}
使用方法:通过控制 visible 属性来控制弹框的显示和隐藏。
import {Button} from 'antd';
import ModalEle from './modalEle';
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
}
showModal = () => {
this.setState({
visible: true
})
}
onCancel = () => {
this.setState({
visible: false
})
}
onOk = () => {
this.setState({
visible: false
})
}
render() {
return (
<div>
<Button onClick={this.showModal}>Ele显示弹框</Button>
<ModalEle visible={visible}
title="Title"
content="test"
onOk={this.onOk}
onCancel={this.cancel}
/>
</div>
)
}
}
通用的弹窗是直接挂载到 document.body 上,比如 Antd 的弹框默认都是挂载到 document.body 上的。但有些时候你也可以自定义挂载的父元素,可以对上面代码稍加改进,把要挂载的父元素, left, top 封装成一个对象传入,然后内部稍微改一下就 OK 了。