Render Props
是一种react组件之间使用prop数据共享的简单技术,是一种开发时可以使用到的一种技巧,可以实现组件的高可复用性。
假设我们有一个需求,需要获取到鼠标在页面中的一个位置,我们可能会这么写:
interface StateInterface{
x:number,
y:number
}
class Mouse extends React.Component<any,StateInterface>{
constructor(props:any){
super(props)
this.state = {
x:0, y:0 }
}
componentDidMount(){
document.addEventListener('mousemove', this.fnGetMousePoint)
}
fnGetMousePoint=(event:any)=>{
this.setState({
x:event.clientX,
y:event.clientY
})
console.log('鼠标的坐标位置:',this.state);
}
render(){
let {
x, y } = this.state
return(
<div>
<div style={
{
position:'absolute',left:x,top:y,width:50,height:50,backgroundColor:'red' }}></div>
</div>
)
}
}
如果另一个组件也需要使用到这个获取到鼠标位置的功能,这个时候就要再复制一份功能代码,无法实现功能的复用。
如果需要使得Mouse组件中的功能复用的话,可能是需要重构一部分react组件中的代码,从而达到可以组件功能复用的条件:
class Mouse extends React.Component{
constructor(props:any){
super(props)
this.state = {
x:0, y:0 }
}
componentDidMount(){
document.addEventListener('mousemove', this.fnGetMousePoint)
}
fnGetMousePoint=(event:any)=>{
this.setState({
x:event.clientX,
y:event.clientY
});
}
render(){
return(
<div>
<Cat mouse={
this.state}/>
</div>
)
}
}
class Cat extends React.Component<any>{
render(){
let {
x,y} = this.props.mouse
return(
<div>
<div style={
{
position:'absolute',left:x-25,top:y-25,width:50,height:50,backgroundColor:'red' }}></div>
</div>
)
}
}
通过重构Mouse组件中的代码,我们实现了让Cat组件复用了鼠标位置的功能,但是仍然不是真正的实现可复用,因为需要在组件中修改相应的代码,才能达到让指定的组件复用其功能,这种将Cat组件硬编码到Mouse组件中的方式显然并不是我们所需要的。
或许我们是时候使用render props这种方式,看示例:
interface StateInterface{
x:number,
y:number
}
class Mouse extends React.Component<any,StateInterface>{
constructor(props:any){
super(props)
this.state = {
x:0, y:0 }
}
componentDidMount(){
document.addEventListener('mousemove', this.fnGetMousePoint)
}
fnGetMousePoint=(event:any)=>{
this.setState({
x:event.clientX,
y:event.clientY
})
}
render(){
return(
<div>
{
this.props.render( this.state ) }
</div>
)
}
}
class Cat extends React.Component<any>{
render(){
let {
x,y} = this.props.mouse
return(
<div>
<div style={
{
position:'absolute',left:x-25,top:y-25,width:50,height:50,backgroundColor:'red' }}></div>
</div>
)
}
}
class MouseTracker extends React.Component{
render(){
return(
<div>
<Mouse render={
(mouse:any)=>(
<Cat mouse={
mouse}/>
)}/>
</div>
)
}
}
我们从Mouse中用一个props拿到一个父组件的render函数,然后将Mouse中的数据以实参的方式传递出去,以父传子的方式将数据传递到Cat组件身上使用,这样就可以实现动态的将数据给Cat组件了,而不是在Mouse组件身上动代码。我们可以利用render props来实现大多数的高阶组件
最后,我们需要注意的是,render prop是因为模式才被称之为render prop,我们不需要局限于render的prop来使用这种模式,我们例子上使用的是render,但是我们也可以使用别的名称来代替这个render,比如使用child prop这种!
<Mouse child={
(mouse:any)=>(
<Cat mouse={
mouse}/>
)}/>
/******************************/
// 使用的时候跟prop一一对应即可
{
this.props.child( this.state ) }