REACT高阶组件面试如何回答得高分

 React中的HOC

1组件是将props转换为UI,而高阶组件是将组件转换为另一个组件

2HOC本质就是一个函数,该函数接受一个组件作为参数,并返回一个新的组件,这是一种模式

3我们可以称之为纯组件,因为他们以接受任何动态提供的子组件,但他们不会修改或复制其输入组件中的任何行为

 HOC用例:

1.代码复用,逻辑抽象化

2.渲染劫持

3.抽象化和操作状态(state)

4.操作属性props

 

下面是官方解释∶

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。

高阶组件(HOC)就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件,它只是一种组件的设计模式,这种设计模式是由react自身的组合性质必然产生的。我们将它们称为纯组件,因为它们可以接受任何动态提供的子组件,但它们不会修改或复制其输入组件中的任何行为。

 

// hoc的定义

function withSubscription(WrappedComponent, selectData) {

  return class extends React.Component {

    constructor(props) {

      super(props);

      this.state = {

        data: selectData(DataSource, props)

      };

    }

    // 一些通用的逻辑处理

    render() {

      // ... 并使用新数据渲染被包装的组件!

      return <WrappedComponent data={this.state.data} {...this.props} />;

    }

  };

 

// 使用

const BlogPostWithSubscription = withSubscription(BlogPost,

  (DataSource, props) => DataSource.getBlogPost(props.id));

1)HOC的优缺点

优点∶ 逻辑服用、不影响被包裹组件的内部逻辑。

缺点∶hoc传递给被包裹组件的props容易和被包裹后的组件重名,进而被覆盖

2)适用场景

 

代码复用,逻辑抽象

渲染劫持

State 抽象和更改

Props 更改

3)具体应用例子

 

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

// HOC.js

function withAdminAuth(WrappedComponent) {

    return class extends React.Component {

        state = {

            isAdmin: false,

        }

        async UNSAFE_componentWillMount() {

            const currentRole = await getCurrentUserRole();

            this.setState({

                isAdmin: currentRole === 'Admin',

            });

        }

        render() {

            if (this.state.isAdmin) {

                return <WrappedComponent {...this.props} />;

            } else {

                return (<div>您没有权限查看该页面,请联系管理员!</div>);

            }

        }

    };

}

 

// pages/page-a.js

class PageA extends React.Component {

    constructor(props) {

        super(props);

        // something here...

    }

    UNSAFE_componentWillMount() {

        // fetching data

    }

    render() {

        // render page with data

    }

}

export default withAdminAuth(PageA);

 

 

// pages/page-b.js

class PageB extends React.Component {

    constructor(props) {

        super(props);

    // something here...

        }

    UNSAFE_componentWillMount() {

    // fetching data

    }

    render() {

    // render page with data

    }

}

export default withAdminAuth(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;

            }

            UNSAFE_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);   

 

 

注意:withTiming 是利用 反向继承 实现的一个高阶组件,功能是计算被包裹组件(这里是 Home 组件)的渲染时间。

 

页面复用

const withFetching = fetching => WrappedComponent => {

    return class extends React.Component {

        state = {

            data: [],

        }

        async UNSAFE_componentWillMount() {

            const data = await fetching();

            this.setState({

                data,

            });

        }

        render() {

            return <WrappedComponent data={this.state.data} {...this.props} />;

        }

    }

}

 

// pages/page-a.js

export default withFetching(fetching('science-fiction'))(MovieList);

// pages/page-b.js

export default withFetching(fetching('action'))(MovieList);

// pages/page-other.js

export default withFetching(fetching('some-other-type'))(MovieList);

好了就到这里吧!!

dad92163be184826ad59789220bb7104.jpg

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值