React开发之——render props模式(16)

一 概述

  • React组件复用概述
  • render props模式思路分析
  • render props模式实现步骤
  • render props模式复用示例(render prop+children)
  • render props模式优化

二 React组件复用概述

2.1 Mouse位置显示和图片跟随

2.2 React组件复用概述

  • 思考:如果两个组件中的部分功能相似或相同,该如何处理?
  • 处理方式:复用相似的功能(联想函数封装)
  • 复用什么?1. state 2. 操作state的方法 (组件状态逻辑 )
  • 两种方式:1. render props模式 2. 高阶组件(HOC)
  • 注意:这两种方式不是新的API,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)

三 render props模式思路分析

3.1 思路

将要复用的state和操作state的方法封装到一个组件中

3.2 问题1:如何拿到该组件中复用的state?

在使用组件时,添加一个值为函数的prop,通过 函数参数 来获取(需要组件内部实现)

1
<Mouse render={(mouse)=>{}} />

3.3 问题2:如何渲染任意的UI?

1
<Mouse render={(mouse)=>(<p>鼠标当前位置:{mouse.x},{mouse.y}</p>)}

四 render props模式实现步骤

4.1 使用步骤

  • 创建Mouse组件,在组件中提供复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
  • 将要复用的状态作为 props.render(state) 方法的参数,暴露到组件外部
  • 使用 props.render() 的返回值作为要渲染的内容

4.2 示例代码

Mouse组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Mouse extends React.Component {
// 鼠标位置state
state = {
x: 0,
y: 0
}

// 鼠标移动事件的事件处理程序
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}

// 监听鼠标移动事件
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}

render() {
return this.props.render(this.state)
}
}

App组件给Mouse传递数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class App extends React.Component {
render() {
return (
<div>
<h1>render props 模式</h1>
<Mouse
render={(mouse) => {
return (
<p>
鼠标位置:{mouse.x} {mouse.y}
</p>
)
}}
/>
</div>
)
}
}

五 render props模式复用示例(render prop+children)

5.1 Mouse组件的复用

复用说明:

  • Mouse组件负责:封装复用的状态逻辑代码(1. 状态 2. 操作状态的方法)
  • 状态:鼠标坐标(x, y)
  • 操作状态的方法:鼠标移动事件
  • 传入的render prop负责:使用复用的状态来渲染UI结构

示例代码

Mouse组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Mouse extends React.Component {
// 鼠标位置state
state = {
x: 0,
y: 0
}

// 鼠标移动事件的事件处理程序
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}

// 监听鼠标移动事件
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}

render() {
return this.props.render(this.state)
}
}

复用组件

1
<Mouse render={mouse => {return (<p>鼠标位置:{mouse.x} {mouse.y}</p>)}}/>

5.2 children代替render属性

childern使用说明:

  • 注意:并不是该模式叫 render props 就必须使用名为render的prop,实际上可以使用任意名称的prop
  • 把prop是一个函数并且告诉组件要渲染什么内容的技术叫做:render props模式
  • 推荐:使用 children 代替 render 属性

示例代码

App组件

1
2
3
<Mouse>
{mouse => {return (<p>鼠标位置:{mouse.x} {mouse.y}</p>)}}
</Mouse>

Mouse组件渲染时

1
2
3
render() {
return this.props.children(this.state)
}

六 render props模式优化

6.1 优化1——给 render props 模式添加 props校验

1
2
3
Mouse.propTypes = {
chidlren: PropTypes.func.isRequired
}

6.2 应该在组件卸载时解除 mousemove 事件绑定

1
2
3
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove)
}