一、认识高阶组件
什么是高阶组件呢? 相信很多人都听说过,也用过 高阶函数,它们非常相似,所以我们可以先来回顾一下什么是 高阶函数。
高阶函数的维基百科定义:至少满足以下条件之一:
- 接受一个或多个函数作为输入;
- 输出一个函数;
JavaScript中比较常见的filter、map、reduce都是高阶函数。
那么什么是高阶组件呢?
- 高阶组件的英文是 Higher-Order Components,简称为 HOC;
- 官方的定义:
高阶组件是参数为组件,返回值为新组件的函数;
我们可以进行如下的解析:
- 首先, 高阶组件 本身不是一个组件,而是一个函数;
- 其次,这个函数的参数是一个组件,返回值也是一个组件;
二、高阶组件的定义
- 高阶组件的调用过程类似于这样:

- 高阶函数的编写过程类似于这样:

组件的名称问题:
- 在ES6中,类表达式中类名是可以省略的;
- 组件的名称都可以通过displayName来修改;



import React, { PureComponent } from 'react'; class App extends PureComponent { render() { return ( <div> app: { this.props.name} </div> ); } } function enhanceComponent2(WrappedComponent) { function NewComponent(props) { return <WrappedComponent { ...props} /> } NewComponent.displayName = 'zep2' return NewComponent } // function enhanceComponent(WrappedComponent) { // class NewComponent extends PureComponent { // render() { // return // } // } // NewComponent.displayName = 'zep' // return NewComponent // } const EnhanceComponent = enhanceComponent2(App) export default EnhanceComponent; 高阶组件并不是React API的一部分,它是基于React的 组合特性而形成的设计模式;
高阶组件在一些React第三方库中非常常见:
- 比如redux中的connect;(后续会讲到)
- 比如react-router中的withRouter;(后续会讲到)
三、高阶组件的应用—— props的增强
利用高阶组件来共享Context:
- 未使用高阶组件共享Context时:
import React, {
PureComponent, createContext} from 'react'; // 创建Context const UserContext = createContext({
nickname: '默认', level: -1, region: '中国' }) class Home extends PureComponent {
render() {
return ( <UserContext.Consumer> {
user => {
return <h2>Home {
`昵称:${
user.nickname} 等级:${
user.level} 区域:${
user.region}`}</h2> } } </UserContext.Consumer> ) } } class About extends PureComponent {
render() {
return ( <UserContext.Consumer> {
user => {
return <h2>Home {
`昵称:${
user.nickname} 等级:${
user.level} 区域:${
user.region}`}</h2> } } </UserContext.Consumer> ) } } class App extends PureComponent {
render() {
return ( <div> app <UserContext.Provider value={
{
nickname: 'zep', level: 50, region: '深圳'}}> <Home/> <About/> </UserContext.Provider> </div> ); } } export default App;

- 使用高阶组件共享Context时:

import React, { PureComponent, createContext} from 'react'; // 定义高阶组件 function withUser(WrappedComponent) { return function (props) { return ( <UserContext.Consumer> { user => { return <WrappedComponent { ...props} { ...user} /> } } </UserContext.Consumer> ) } } // 创建Context const UserContext = createContext({ nickname: '默认', level: -1, region: '中国' }) class Home extends PureComponent { render() { return <h2>Home { `昵称:${ this.props.nickname} 等级:${ this.props.level} 区域:${ this.props.region}`}</h2> } } class About extends PureComponent { render() { return <h2>Home { `昵称:${ this.props.nickname} 等级:${ this.props.level} 区域:${ this.props.region}`}</h2> } } const UserHome = withUser(Home) const UserAbout = withUser(About) class App extends PureComponent { render() { return ( <div> app <UserContext.Provider value={ { nickname: 'zep', level: 50, region: '深圳'}}> <UserHome/> <UserAbout/> </UserContext.Provider> </div> ); } } export default App; 四、高阶组件的应用—— 渲染判断鉴权
在开发中,我们可能遇到这样的场景:
- 某些页面是必须用户登录成功才能进行进入;
- 如果用户没有登录成功,那么直接跳转到登录页面;
import React, {
PureComponent} from 'react'; // 高阶组件 function withAuth (WrappedComponent) {
const NewCpn = function (props) {
const {
isLogin} = props if (isLogin) {
return <WrappedComponent {
...props} /> } else {
return <LoginPage {
...props} /> } } NewCpn.displayName = 'AuthCpn' return NewCpn } // 登录组件 class LoginPage extends PureComponent {
render() {
return <h2>LoginPage</h2> } } // 购物车组件 class CartPage extends PureComponent {
render() {
return <h2>CartPage</h2> } } const AuthCartPage = withAuth(CartPage) class App extends PureComponent {
render() {
return ( <div> <AuthCartPage isLogin={
false} /> </div> ); } } export default App;
五、高阶组件的应用—— 生命周期劫持
import React, {
PureComponent} from 'react'; function withRenderTime(WrappedComponent) {
return class extends PureComponent {
// 即将渲染时获取当前的时间 componentWillMount() {
this.beginTime = Date.now() } // 渲染完成再获取当前时间 componentDidMount() {
this.endTime = Date.now() const interval = this.endTime - this.beginTime console.log(`${
WrappedComponent.name}渲染时间: ${
interval}`) } render() {
return <WrappedComponent {
...this.props} /> } } } class Home extends PureComponent{
/* // 即将渲染时获取当前的时间 componentWillMount() { this.beginTime = Date.now() }*/ render() {
return <h2>Home</h2> } /*// 渲染完成再获取当前时间 componentDidMount() { this.endTime = Date.now() const interval = this.endTime - this.beginTime console.log('Home渲染时间:' + interval) }*/ } class About extends PureComponent{
render() {
return <h2>About</h2> } } const TimeHome = withRenderTime(Home) const TimeAbout = withRenderTime(About) class App extends PureComponent {
render() {
return ( <div> App <TimeHome /> <TimeAbout /> </div> ); } } export default App;
六、高阶函数的意义
- Mixin 可能会相互依赖,相互耦合,不利于代码维护
- 不同的Mixin中的方法可能会相互冲突
- Mixin非常多时,组件是可以感知到的,甚至还要为其做相关处理,这样会给代码造成滚雪球式的复杂性
当然,HOC也有自己的一些缺陷:
- HOC需要在原组件上进行包裹或者嵌套,如果大量使用HOC,将会产生非常多的嵌套,这让调试变得非常困难;
- HOC可以劫持props,在不遵守约定的情况下也可能造成冲突;
Hooks的出现,是开创性的,它解决了很多React之前的存在的问题
- 比如this指向问题
- 比如hoc的嵌套复杂度问题等
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200431.html原文链接:https://javaforall.net
