react组件插槽 - 实现自己的可扩展的组件
2019-06-04 本文已影响0人
小小的开发人员
需求
我们自己写了个组件,引用组件时想要在组件中写入内容,并且写入的内容可以被组件识别、控制,用过Vue的同学肯定会立刻想到slot插槽,react也支持插槽功能,下面我们用react开发一个支持插槽功能的组件。
核心思想
父组件在子组件中传入的三个div,这三个div会默认通过props传到子组件中,然后我们在子组件中控制children的渲染即可。
<Window display={this.state.display}>
//父组件在子组件中传入的三个div,
<div papa="title">title</div>
<div papa="content">content</div>
<div papa="foot">foot</div>
</Window>
知道了react的插槽实现方式,我们来实现一个支持插槽的组件。
完成组件Pop
import React from 'react';
import {Fragment, Component} from 'react';
import { connect } from 'react-redux'
import './index.scss'
import { Icon, Button } from 'zent'
class Pop extends Component {
constructor(props) {
super(props);
this.state = {}
this.renderChild = this.renderChild.bind(this)
}
render() {
return (
<Fragment>
<div className="pop-wrap">
<div className="pop-header">
<span className="left">{this.props.popTitle}</span>
<Icon className="right" type="close"/>
</div>
<div className="pop-content">
{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.Group>
<Button size="small" className="cancel">取消</Button>
<Button size="small" type="primary" className="confirm">确定</Button>
</Button.Group>
</div>
</div>
</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>
}
}
}
const mapStateToProps = (state) => {
return {
}
}
const mapDispatchToProps = (dispatch) => {
return {}
}
export default connect(mapStateToProps, mapDispatchToProps)(Pop)
Pop的scss文件
.pop-wrap {
position:absolute;
left:0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
z-index: 2;
width: 350px;
height: 300px;
border: 1px solid #C8C8C8;
border-radius: 2px;
}
.pop-header {
height: 40px;
display: flex;
align-items: center;
border-bottom: 1px solid #C8C8C8;
.left{
flex: 10;
margin-left: 10px;
}
.right {
flex: 1;
margin-right: 10px;
}
}
.pop-content {
display: flex;
height: 220px;
.left, .right, .center {
display: flex;
justify-content: center;
padding-top: 10px;
}
.left,.right {
flex: 1;
}
.center {
width: 100%;
}
.right{
border-left: 1px solid #C8C8C8;
}
}
.pop-footer {
height: 40px;
display: flex;
align-items: center;
border-top: 1px solid #C8C8C8;
flex-direction: row-reverse;
.cancel, .confirm{
margin-right: 10px;
}
}
引用子组件