React组件复用概述
- 思考:如果两个组件中的部分功能相似或相同,该如何处理?
- 处理方式:
复用
相似的功能(联想函数封装) - 复用什么? 1.
state
2. 操作state的方法
(组件状态逻辑) - 两种方式:1.
render props
模式 2. 高阶组件(HOC)
- 注意:这两种方式
不是新的APl
,而是利用React自身特点的编码技巧,演化而成的固定模式(写法)
render props 模式
- 思路:将要复用的 state 和操作 state 的方法封装到一个组件中
- 问题1:如何拿到该组件中复用的 state ?
- 在使用组件时,添加一个值为
函数的 prop
,通过函数参数
来获取(需要组件内部实现) - 问题2:如何渲染任意的UI?
- 使用
该函数的返回值
作为要渲染的UI内容(需要组件内部实现)
使用步骤
- 创建 Mouse 组件,在组件中提供复用的
状态逻辑
代码(1.状态 2.操作状态的方法) - 将要
复用的状态
作为 props.render(state
) 方法的参数,暴露到组件外部 - 使用 props.render() 的
返回值
作为要渲染的内容
import React from "react";
import ReactDOM from "react-dom";
import './index.css'
class Mouse extends React.Component {
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)
)
}
}
class App extends React.Component {
render() {
return(
<div>
<h1>render props 模式</h1>
<Mouse render={mouse => {
return (
<p>鼠标位置:{mouse.x} {mouse.y}</p>
)
}} />
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"))
children代替render属性
- 注意:并不是该模式叫 render props 就必须使用名为 render 的 prop,实际上可以使用任意名称的 prop
- 把 prop 是一个函数并且告诉组件要渲染什么内容的技术叫做:render props 模式
- 推荐:使用
children
代替 render 属性
import React from "react";
import ReactDOM from "react-dom";
import './index.css'
class Mouse extends React.Component {
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.children(this.state)
)
}
}
class App extends React.Component {
render() {
return(
<div>
<h1>render props 模式</h1>
<Mouse render>
{mouse => {
return (
<p>鼠标位置:{mouse.x} {mouse.y}</p>
)
}}
</Mouse>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"))
代码优化
- 推荐:给render props模式添加props校验
- 应该在组件卸载时解除 mousemove 事件绑定
import React from "react";
import ReactDOM from "react-dom";
import Proptypes from "prop-types"
import './index.css'
class Mouse extends React.Component {
state = {
x: 0,
y: 0
}
handleMouseMove = e => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove)
}
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove)
}
render() {
return (
this.props.children(this.state)
)
}
}
Mouse.propTypes = {
children: Proptypes.func.isRequired
}
class App extends React.Component {
render() {
return(
<div>
<h1>render props 模式</h1>
<Mouse render>
{mouse => {
return (
<p>鼠标位置:{mouse.x} {mouse.y}</p>
)
}}
</Mouse>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById("root"))