706 字
4 分钟
04.高阶组件
高阶组件的英文是 Higher-Order Components,简称为 HOC;
官方的定义:高阶组件是参数为组件,返回值为新组件的函数;
根据上文:
高阶组件本身不是一个组件,而是一个函数;
这个函数的参数是一个组件,返回值也是一个组件。
function enhanceComponent(WrappedComponent) {
return class NewComponent extends PureComponent {
render() {
return <WrappedComponent/>
}
}
}
高阶组件并不是React API的一部分,它是基于React的组合特性而形成的设计模式;
高阶组件在一些React第三方库中非常常见:
比如 redux 中的 connect 和 react-router 中的 withRouter。
高阶组件的一些应用
props增强
使用高阶组件可以对多个组件添加多个相同的 props 参数:
import React, { PureComponent } from 'react'
class App extends PureComponent {
render() {
return (
<div>
App
<EnhanceHome name='Sytus' age={17}></EnhanceHome>
<EnhanceAbout name='Ram' age={20}></EnhanceAbout>
</div>
)
}
}
class Home extends PureComponent {
render() {
return (
<div>
<h2>Home: {this.props.name + ' ' + this.props.age + ' ' + this.props.region}</h2>
</div>
)
}
}
const EnhanceHome = enhanceRegionProps(Home)
class About extends PureComponent {
render() {
return (
<div>
<h2>About: {this.props.name + ' ' + this.props.age + ' ' + this.props.region}</h2>
</div>
)
}
}
const EnhanceAbout = enhanceRegionProps(About)
function enhanceRegionProps(WrappedComponent) {
return props => {
return <WrappedComponent {...props} region='China'/>
}
}
export default App
渲染判断鉴权
使用高阶组件可以对具有判断需求的组件进行处理:
import React, { PureComponent } from 'react'
function withAuth(WrappedComponent) {
return props => {
const { isLogin } = props
if (isLogin) {
return <WrappedComponent {...props} />
} else {
return <LoginPage></LoginPage>
}
}
}
export default class App extends PureComponent {
render() {
return (
<div>
<AuthCartPage isLogin={false}></AuthCartPage>
</div>
)
}
}
class CartPage extends PureComponent {
render() {
return (
<div>
<h2>CartPage</h2>
</div>
)
}
}
const AuthCartPage = withAuth(CartPage)
class LoginPage extends PureComponent {
render() {
return (
<div>
<h2>LoginPage</h2>
</div>
)
}
}
生命周期劫持
在面对一些需求时,我们可能需要在多个生命周期中进行处理数据,比如计算 render 函数的渲染时间:
import React, { PureComponent } from 'react'
function withRenderTime(WrappedComponent) {
return class NewComponent extends PureComponent {
UNSAFE_componentWillMount() {
this.beginTime = Date.now()
}
componentDidMount() {
this.endTime = Date.now()
console.log(WrappedComponent.name, this.endTime - this.beginTime + 'ms');
}
render() {
return <WrappedComponent {...this.props}></WrappedComponent>
}
}
}
class App extends PureComponent {
render() {
return (
<div>
App
<TimeHome name='Sytus' age={17}></TimeHome>
<TimeAbout name='Ram' age={20}></TimeAbout>
</div>
)
}
}
class Home extends PureComponent {
render() {
return (
<div>
<h2>Home</h2>
</div>
)
}
}
class About extends PureComponent {
render() {
return (
<div>
<h2>About</h2>
</div>
)
}
}
const TimeHome = withRenderTime(Home)
const TimeAbout = withRenderTime(About)
export default App
高阶组件的意义
高阶组件可以针对某些 React 代码进行更加优雅的处理。
但 HOC 也有自己的一些缺陷:
HOC 需要在原组件上进行包裹或嵌套,如果大量使用 HOC,将会产生非常多的嵌套,这让调试变得非常困难;
HOC 可以劫持 props,在不遵守约定的情况下也可能造成冲突。
Hooks 的出现,是开创性的,它解决了 React 之前存在的问题,比如 this 指向问题,比如 HOC 的嵌套复杂问题等等。