组件的复用目前有三种形式:
- 高阶组件(HOC)
- 渲染属性(Render Props)
- Hooks
1、高阶组件(higher order component,即HOC)
1.1、是什么
-
高阶组件是React中
用于复用组件逻辑的一种高级技巧
。 -
高阶组件就是一个函数,它接受一个组件为参数,返回一个新组件。
-
示例如下:
import React from 'react' import ReactDOM from 'react-dom' // 函数 const withMouse = (Component) => { return class extends React.Component { state = { x: 0, y: 0 } handleMouseMove = (event) => { this.setState({ x: event.clientX, y: event.clientY }) } render() { return ( <div style={ { height: '100%' }} onMouseMove={ this.handleMouseMove}> <Component { ...this.props} mouse={ this.state}/> </div> ) } } } // 组件 const App = (props) => { const { x, y } = props.mouse return ( <div style={ { height: '100%' }}> <h1>The mouse position is ({ x}, { y})</h1> </div> ) } //通过函数,输出一个新的组件,即高阶组件HOC const AppWithMouse = withMouse(App) ReactDOM.render(<AppWithMouse/>, document.getElementById('root'))
1.2、HOC的约定
- 将不相关的 props传递给被包裹的组件(HOC应透传与自身无关的 props)
- 最大化可组合性
- 包装显示名称以便调试
1.3、HOC的注意事项
- 不要在函数内修改原组件
- 使用反向继承方式时,会丢失原本的显示名
- 不要在 render函数中使用HOC
1.4、HOC的缺点
- 难以溯源。如果原始组件A通过好几个HOC的构造,最终生成了组件B,这个就不知道哪个属性来自于哪个HOC,需要翻看每个HOC才知道各自做了什么事情,使用了什么属性
- props属性名的冲突。某个属性可能被多个HOC重复使用。
- 静态构建。新的组件是在页面构建之前生成,先有组件,后生成页面
2、React的渲染属性(Render Props)
-
Render Props 的核心思想是,通过一个函数将class组件的state作为props传递给纯函数组件
-
示例如下:
import React from 'react' import ReactDOM from 'react-dom' import PropTypes from 'prop-types' // class Mouse extends React.Component { static propTypes = { render: PropTypes.func.isRequired } state = { x: 0, y: 0 } handleMouseMove = (event) => { this.setState({ x: event.clientX, y: event.clientY }) } render() { return ( <div style={ { height: '100%' }} onMouseMove={ this.handleMouseMove}> { this.props.render(this.state)} </div> ) } } const App = () => ( <div style={ { height: '100%' }}> <Mouse render={ ({ x, y }) => ( <h1>The mouse position is ({ x}, { y})</h1> )}/> </div> ) ReactDOM.render(<App/>, document.getElementById('root'))
-
示例的核心分析
从demo中很容易看到,新建的Mouse组件的render方法中返回了{this.props.render(this.state)}这个函数,将其state作为参数传入其的props.render方法中,调用时直接取组件所需要的state即可。
-
相对HOC的优势
1、可以溯源,子组件的props一定来自父组件
2、不用担心props的命名问题
3.、不会产生无用的空组件加深层级
4.、构建模型是动态的,所有改变都在render中触发,能更好的利用react的生命周期。
5、所有HOC能完成的事,Render Props都可以完成
6、除了功能的复用,还有两个组件之间单向数据流的传递
3、Hooks
3.1、示例
import React, fusestate from 'react
import (IView, Text, Button) from ' react-native
export default function Hook Count()(
const [count, addCount, minusCount ]= countNumber(0);
return (
<View>
<Text>You clicked {
count} times</Text>
<Button onPress={
addcount } title="add" />
<Button onPress={
minusCount } title="minu" />
</View>
)
}
function countNumber (initNumber)(
const [count, setCount] = usestate(initNumber)
const addCount = ()=> setCount(count+1)
const minusCount = ()=> setCount(count-1)
return [
count,
addCount,
minusCount
]
}
Hooks的优势不仅体现在代码量上,从风格上来说,也显得语义更淸晰、结构更优雅(相比之下,高阶组件和 Render Props的语法都显得比较诡异)。
更重要的是,上述两种模式所拥有的种种缺点,它一个都没有,当我们复用的逻辑达到多个的时候,这种优势会表现得更加明显。