高阶组件

150 阅读2分钟

什么是高阶组件

在解释什么是高阶组件之前,可以先了解一下什么是 高阶函数,因为它们的概念非常相似,下面是 高阶函数 的定义:

如果一个函数 接受一个或多个函数作为参数或者返回一个函数 就可称之为 高阶函数

高阶组件 的定义和 高阶函数 非常相似:

如果一个函数 接受一个或多个组件作为参数并且返回一个组件 就可称之为 高阶组件

高阶函数的意义

image.png

高阶组件的应用

权限控制

利用高阶组件的 条件渲染 特性可以对页面进行权限控制,权限控制一般分为两个维度:页面级别页面元素级别,这里以页面级别来举一个栗子:

// HOC.js

function withAdminAuth(WrappedComponent) {
    return class extends React.Component {
        state = {
            isAdmin: false,
        }
        async componentWillMount() {
            const currentRole = await getCurrentUserRole();
            this.setState({
                isAdmin: currentRole === 'Admin',
            });
        }
        render() {
            if (this.state.isAdmin) {
                return <WrappedComponent {...this.props} />;
            } else {
                return (<div>您没有权限查看该页面,请联系管理员!</div>);
            }
        }
    };
}

页面复用

假设我们有两个页面 pageApageB 分别渲染两个分类的电影列表,普通写法可能是这样:

// pages/page-a.js
class PageA extends React.Component {
    state = {
        movies: [],
    }
    // ...
    async componentWillMount() {
        const movies = await fetchMoviesByType('science-fiction');
        this.setState({
            movies,
        });
    }
    render() {
        return <MovieList movies={this.state.movies} />
    }
}
export default PageA;

// pages/page-b.js
class PageB extends React.Component {
    state = {
        movies: [],
    }
    // ...
    async componentWillMount() {
        const movies = await fetchMoviesByType('action');
        this.setState({
            movies,
        });
    }
    render() {
        return <MovieList movies={this.state.movies} />
    }
}
export default PageB;

组件渲染性能追踪

借助父组件子组件生命周期规则捕获子组件的生命周期,可以方便的对某个组件的渲染时间进行记录:

class Home extends React.Component {
    render() {
        return (<h1>Hello World.</h1>);
    }
}



function withTiming(WrappedComponent) {

    return class extends WrappedComponent {
       constructor(props) {
            super(props);
            this.start = 0;
            this.end = 0;
        }
        componentWillMount() {
            super.componentWillMount && super.componentWillMount();
            this.start = Date.now();
       }
        componentDidMount() {
            super.componentDidMount && super.componentDidMount();
            this.end = Date.now();
            console.log(`${WrappedComponent.name} 组件渲染时间为 ${this.end - this.start} ms`);

        }
        render() {

           return super.render();
        }
    };
}
export default withTiming(Home);

Ref的转发

react封装好的组件

forwardRef 高阶组件从react导入

image.png

Portals的使用

image.png

总结

React 中的 高阶组件 其实是一个非常简单的概念,但又非常实用。在实际的业务场景中合理的使用高阶组件,可以提高代码的复用性和灵活性

最后的最后,再对高阶组件进行一个小小的总结:

  • 高阶组件 不是组件 一个把某个组件转换成另一个组件的 函数
  • 高阶组件的主要作用是 代码复用
  • 高阶组件是 装饰器模式在 React 中的实现