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