效果图如上:
1.点击按钮出现弹窗,点击弹窗的x按钮隐藏弹窗;
2.插槽可以是组件,可以是直接写div等代码;
3.确认保存按钮功能没做,主要是为了布局效果而已;
直接看代码:
components/App.js
import React from 'react';
import PopContainer from '../containers/PopContainer'
import Slot from '../containers/SlotContainer'
import Slot1 from './slot1'
import Slot2 from './slot2'
import Slot3 from './slot3'
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
left: 'left',
right: 'right',
center: 'center',
show: false,
}
}
showing = (show) => {
this.setState({
show,
})
}
render() {
return (
<div>
<button onClick={()=>{
this.setState({
show: !this.state.show,
})
}}>弹窗</button>
<PopContainer show={this.state.show} showing={this.showing.bind(this)}>
<Slot></Slot>
<Slot1 left={this.state.left}></Slot1>
<Slot2 center={this.state.center}></Slot2>
<Slot3 right={this.state.right}></Slot3>
</PopContainer>
</div>
);
};
}
App.propTypes = {};
export default App;
comnponents/Pop.js
import React from 'react';
import { Fragment, Component } from 'react';
import './index.scss'
import { Button } from 'antd'
import {
CloseOutlined,
} from '@ant-design/icons';
class Pop extends Component {
constructor(props) {
super(props);
this.state = {
popTitle: '弹窗',
show: false,
}
this.renderChild = this.renderChild.bind(this)
}
componentDidCatch =() =>{
}
render() {
return (
<Fragment>
{
this.props.show ?
<div className="pop-wrap">
<div className="pop-header">
<span className="left">{this.state.popTitle}</span>
<CloseOutlined onClick={() => {
this.props.showing(false);
}}/>
</div>
<div className="pop-content">
{this.props.show+''}
{/* {this.props.children} */}
{Array.isArray(this.props.children) ?
this.props.children.map((child) => {
return this.renderChild(child)
}) : this.props.children && this.renderChild(this.props.children)}
</div>
<div className="pop-footer">
<Button type="primary">确认</Button>
<Button>保存</Button>
</div>
</div>
: null
}
</Fragment>
)
}
renderChild(child) { // 控制内容的分发
if (child.props.left) {
return <div className="left" key="left">{child}</div>
} else if (child.props.right) {
return <div className="right" key="right">{child}</div>
} else if (child.props.center) {
return <div className="center" key="center">{child}</div>
}
return child;
}
};
export default Pop;
containers/PopContainer.js
import { connect } from 'react-redux'
import Pop from '../components/Pop'
const mapStateToProps = (state) => {
return {
}
}
const mapDispatchToProps = (dispatch) => {
return {
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Pop)
components/slot.js
import React from 'react';
import PropTypes from 'prop-types';
import 'antd/dist/antd.css'
import { Form, Input, Button, Checkbox, Table } from 'antd';
const layout = {
labelCol: {
span: 28,
},
wrapperCol: {
span: 116,
},
};
const tailLayout = {
wrapperCol: {
offset: 88,
span: 186,
},
};
class slot extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
tabledata: []
};
this._tabledata = [];
}
componentDidMount() {
this.setState({
tabledata: this.props.dataSource
});
}
render = () => {
const onFinish = (values) => {
console.log('Success:', values);
let val = this.props.setUsername(values);
this.setState({
loading: true
})
Promise.resolve(val).then(() => {
Object.assign(val, { key: this.state.tabledata.length })
this._tabledata.push(val);
setTimeout(() => {
this.setState({
loading: false,
tabledata: [...this.props.dataSource, ...this._tabledata]
})
}, 100);
})
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
return (
<>
<Form
{...layout}
name="basic"
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
label="Username"
name="username"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Please input your password!',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="Age"
name="age"
rules={[
{
required: true,
message: 'Please input your age!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Address"
name="address"
rules={[
{
required: true,
message: 'Please input your address!',
},
]}
>
<Input />
</Form.Item>
<Form.Item {...tailLayout} name="remember" valuePropName="checked">
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
<Table dataSource={this.state.tabledata} columns={this.props.columns} loading={this.state.loading} />
</>
);
};
}
slot.propTypes = {};
export default slot;
containers/SlotContainer.js
import { connect } from 'react-redux'
import Slot from '../components/slot'
const dataSource = [
{
key: '--',
username: '晋安',
age: 32,
address: '北京',
},
];
const columns = [
{
title: '姓名',
dataIndex: 'username',
key: 'username',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
];
const mapStateToProps = (state) => {
return {
dataSource,
columns,
}
}
const setUsername = text => ({
type: 'username',
...text,
})
const mapDispatchToProps = (dispatch) => {
return {
setUsername: text => dispatch(setUsername(text)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(Slot)
slot1.js,slot2.js,slot3.js
slot1.js
import React from 'react';
import PropTypes from 'prop-types';
class slot1 extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<div>
<div left="true">{this.props.left}</div>
<ul>
<li>react</li>
<li>redux</li>
<li>react-redux</li>
</ul>
</div>
);
}
}
slot1.propTypes = {};
export default slot1;
slot2.js
import React from 'react';
import PropTypes from 'prop-types';
class slot2 extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div center="true">{this.props.center}</div>
</div>
);
}
}
slot2.propTypes = {};
export default slot2;
slot3.js
import React from 'react';
import PropTypes from 'prop-types';
class slot3 extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div right="true">{this.props.right}</div>
</div>
);
}
}
slot3.propTypes = {};
export default slot3;
布局代码index.scss
.pop-wrap {
display: flex;
flex-direction: column;
padding: 0 15px;
position: absolute;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
margin: auto;
z-index: 2;
width: 80vw;
min-height: 680px;
border: 1px solid #C8C8C8;
border-radius: 5px;
&.hide {
display: none;
}
}
.pop-header {
height: 40px;
flex: 0 0 40px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #C8C8C8;
}
.pop-content {
flex: 1;
margin-top: 10px;
width: 100%;
display: flex;
flex-wrap: wrap;
&>form {
width: 100%;
&+div {
width: 100%;
}
}
.left, .right, .center {
flex: 1;
text-align: center;
}
}
.pop-footer {
height: 40px;
flex: 0 0 40px;
display: flex;
align-items: center;
border-top: 1px solid #C8C8C8;
flex-direction: row-reverse;
}