Render props

背景如下:

有时候,某些组件的各种功能及其处理逻辑几乎完全相同,只是显示的界面不一样,建议下面的方式认选其一来解决重复代码的问题(横切关注点)

  1. render props
  2. HOC

组件1:

import React, { PureComponent } from 'react'
import "./style.css"

export default class MovablePanel extends PureComponent {

    state = {
        x: 0,
        y: 0
    }

    divRef = React.createRef()

    handleMouseMove = e => {
        //更新x和y的值
        const { left, top } = this.divRef.current.getBoundingClientRect();
        const x = e.clientX - left;
        const y = e.clientY - top;
        this.setState({
            x,
            y
        });
    }

    render() {
        return (
            <div ref={this.divRef} className="point" onMouseMove={this.handleMouseMove}>
                <div style={{
                    width: 100,
                    height: 100,
                    background: "#008c8c",
                    position: "absolute",
                    left: this.state.x - 50,
                    top: this.state.y - 50
                }}>

                </div>
            </div>
        )
    }
}


组件2:

import React, { PureComponent } from 'react'
import "./style.css"

export default class ShowMousePoint extends PureComponent {

    state = {
        x: 0,
        y: 0
    }

    divRef = React.createRef()

    handleMouseMove = e => {
        //更新x和y的值
        const { left, top } = this.divRef.current.getBoundingClientRect();
        const x = e.clientX - left;
        const y = e.clientY - top;
        this.setState({
            x,
            y
        });
    }

    render() {
        return (
            <div ref={this.divRef} className="point" onMouseMove={this.handleMouseMove}>
                <h2>
                    鼠标x:{parseInt(this.state.x)},
                    鼠标y:{parseInt(this.state.y)}
                </h2>
            </div>
        )
    }
}


这里两个组件其实基本功能一直,都是获取当前鼠标的位置从而显示需要的页面,不同的只是渲染的部分不一样,但是这样的组件明显代码冗余,那么我们如何进行解决呢?

过MouseListener 组件专门去获取当前鼠标位置,具体显示什么?只需要传入我们需要的页面组件即可,这里就应用到了react传递元素内容children,并且通过children传递页面组件需要的参数。

import MouseListener from "./MouseListener";
import React from 'react'

const renderPoint = mouse => <>横坐标:{mouse.x},纵坐标:{mouse.y}</>
const renderDiv = mouse => <>
    <div style={{
        width: 100,
        height: 100,
        background: "#008c8c",
        position: "absolute",
        left: mouse.x - 50,
        top: mouse.y - 50
    }}>

    </div>
</>

export default function Test() {
    return (
        <div>
            <MouseListener>
                {renderPoint} // 这里写啥,MouseListener中就是显示啥,一开始我们只想写坐标值x,y
                              // 但是x,y的值是在MouseListener组件中,我们无法得到,是不是熟悉的味道   
                              // 是的,这里有点像js中回调函数的感觉
                             // 传递一个函数过去,然后直接调用即可,将和你住的返回结果直接渲染出来
            </MouseListener>
            <MouseListener>
                {renderDiv}
            </MouseListener>
        </div>
    )
}

import React, { PureComponent } from 'react'
import "./style.css"

/**
 * 该组件用于监听鼠标的变化
 */
//MouseListener
import React, { PureComponent } from 'react'
import "./style.css"

/**
 * 该组件用于监听鼠标的变化
 */
export default class MouseListener extends PureComponent {
    state = {
        x: 0,
        y: 0
    }

    divRef = React.createRef()

    handleMouseMove = e => {
        //更新x和y的值
        const { left, top } = this.divRef.current.getBoundingClientRect();
        const x = e.clientX - left;
        const y = e.clientY - top;
        this.setState({
            x,
            y
        });
    }

    render() {
        return (
            <div ref={this.divRef} className="point" onMouseMove={this.handleMouseMove}>
                {this.props.children ? this.props.children(this.state) : "默认值"}
            </div>
        )
    }
}

那为什么要叫render props呢?因为我们通常是以下写法,因为是在render中传递属性,而且该属性是个方法,所以叫render props

import React, { PureComponent } from 'react'
import "./style.css"

/**
 * 该组件用于监听鼠标的变化
 */
export default class MouseListener extends PureComponent {
    state = {
        x: 0,
        y: 0
    }

    divRef = React.createRef()

    handleMouseMove = e => {
        //更新x和y的值
        const { left, top } = this.divRef.current.getBoundingClientRect();
        const x = e.clientX - left;
        const y = e.clientY - top;
        this.setState({
            x,
            y
        });
    }

    render() {
        return (
            <div ref={this.divRef} className="point" onMouseMove={this.handleMouseMove}>
                {this.props.render ? this.props.render(this.state) : "默认值"}
            </div>
        )
    }
}


import MouseListener from "./MouseListener";
import React from 'react'

const renderPoint = mouse => <>横坐标:{mouse.x},纵坐标:{mouse.y}</>
const renderDiv = mouse => <>
    <div style={{
        width: 100,
        height: 100,
        background: "#008c8c",
        position: "absolute",
        left: mouse.x - 50,
        top: mouse.y - 50
    }}>

    </div>
</>

export default function Test() {
    return (
        <div>
            <MouseListener render={renderPoint} />
            <MouseListener render={renderDiv} />
        </div>
    )
}

总结如下:
render props

  1. 某个组件,需要某个属性,该属性是一个函数,函数的返回值用于渲染
  2. 函数的参数会传递为需要的数据
  3. 注意纯组件的属性(尽量避免每次传递的render props的地址不一致)
    即将函数单独写一下,render={renderPoint}
  4. 通常该属性的名字叫做render,但不是强制要求的。

你可能感兴趣的:(React,js,前端,javascript,开发语言,ecmascript,react.js)