React中的Render Props模式

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 ) }

おすすめ

転載: blog.csdn.net/cautionHua/article/details/115912326
おすすめ