深圳建立网站营销,外网视频网站做泥声控,重庆最新消息今天封城了,做app和做网站区别面试官#xff1a;说说对高阶组件的理解#xff1f;应用场景? 一、是什么
高阶函数#xff08;Higher-order function#xff09;#xff0c;至少满足下列一个条件的函数
接受一个或多个函数作为输入输出一个函数
在React中#xff0c;高阶组件即接受一个或多个组件作…面试官说说对高阶组件的理解应用场景? 一、是什么
高阶函数Higher-order function至少满足下列一个条件的函数
接受一个或多个函数作为输入输出一个函数
在React中高阶组件即接受一个或多个组件作为参数并且返回一个组件本质也就是一个函数并不是一个组件
const EnhancedComponent highOrderComponent(WrappedComponent);上述代码中该函数接受一个组件WrappedComponent作为参数返回加工过的新组件EnhancedComponent
高阶组件的这种实现方式本质上是一个装饰者设计模式
二、如何编写
最基本的高阶组件的编写模板如下
import React, { Component } from react;export default (WrappedComponent) {return class EnhancedComponent extends Component {// do somethingrender() {return WrappedComponent /;}}
}通过对传入的原始组件 WrappedComponent 做一些你想要的操作比如操作 props提取 state给原始组件包裹其他元素等从而加工出想要的组件 EnhancedComponent
把通用的逻辑放在高阶组件中对组件实现一致的处理从而实现代码的复用
所以高阶组件的主要功能是封装并分离组件的通用逻辑让通用逻辑在组件间更好地被复用
但在使用高阶组件的同时一般遵循一些约定如下
props 保持一致你不能在函数式无状态组件上使用 ref 属性因为它没有实例不要以任何方式改变原始组件 WrappedComponent透传不相关 props 属性给被包裹的组件 WrappedComponent不要再 render() 方法中使用高阶组件使用 compose 组合高阶组件包装显示名字以便于调试
这里需要注意的是高阶组件可以传递所有的props但是不能传递ref
如果向一个高阶组件添加refe引用那么ref 指向的是最外层容器组件实例的而不是被包裹的组件如果需要传递refs的话则使用React.forwardRef如下
function withLogging(WrappedComponent) {class Enhance extends WrappedComponent {componentWillReceiveProps() {console.log(Current props, this.props);console.log(Next props, nextProps);}render() {const {forwardedRef, ...rest} this.props;// 把 forwardedRef 赋值给 refreturn WrappedComponent {...rest} ref{forwardedRef} /;}};// React.forwardRef 方法会传入 props 和 ref 两个参数给其回调函数// 所以这边的 ref 是由 React.forwardRef 提供的function forwardRef(props, ref) {return Enhance {...props} forwardRef{ref} /}return React.forwardRef(forwardRef);
}
const EnhancedComponent withLogging(SomeComponent);三、应用场景
通过上面的了解高阶组件能够提高代码的复用性和灵活性在实际应用中常常用于与核心业务无关但又在多个模块使用的功能如权限控制、日志记录、数据校验、异常处理、统计上报等
举个例子存在一个组件需要从缓存中获取数据然后渲染。一般情况我们会如下编写
import React, { Component } from reactclass MyComponent extends Component {componentWillMount() {let data localStorage.getItem(data);this.setState({data});}render() {return div{this.state.data}/div}
}上述代码当然可以实现该功能但是如果还有其他组件也有类似功能的时候每个组件都需要重复写componentWillMount中的代码这明显是冗杂的
下面就可以通过高价组件来进行改写如下
import React, { Component } from reactfunction withPersistentData(WrappedComponent) {return class extends Component {componentWillMount() {let data localStorage.getItem(data);this.setState({data});}render() {// 通过{...this.props} 把传递给当前组件的属性继续传递给被包装的组件WrappedComponentreturn WrappedComponent data{this.state.data} {...this.props} /}}
}class MyComponent2 extends Component { render() {return div{this.props.data}/div}
}const MyComponentWithPersistentData withPersistentData(MyComponent2)再比如组件渲染性能监控如下
class Home extends React.Component {render() {return (h1Hello 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);参考文献
https://whyta.cn/post/8d761f218aa9/https://zh-hans.reactjs.org/docs/higher-order-components.html#gatsby-focus-wrapperhttps://segmentfault.com/a/1190000010307650https://zhuanlan.zhihu.com/p/61711492