高阶组件(HOC Higher-Order Component):高阶组件是参数为组件,返回值为新组件的函数。
也就是一个函数,接收要包装的组件,返回增强后的组件。
const EnhancedComponent = higherOrderComponent(WrappedComponent);
higherOrderComponent: 高阶组件,是一个函数
WrappedComponent: 要包装的组件
EnhancedComponent: 包装之后的增强组件,
组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。
创建一个高阶组件
// 创建高阶组件
// 1. 约定 名称以 with 开头
// 2. 约定参数名称以大写字母开头,因为其实是个组件
function withMouse(WrappedComponent) {
// 3. 创建一个类组件
class Mouse extends React.Component {
// 4. 在类组件中,提供要复用的状态和方法
state = {
x: 0,
y: 0,
};
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove);
}
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove);
}
handleMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY,
});
};
render() {
// props 可以访问到 age属性
console.log('mouse', this.props)
// return <WrappedComponent {...this.state} />;
return <WrappedComponent {...this.state} {...this.props} />;
}
}
// 设置 displayName 是为了调试区分
Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`;
// 5. 将新组件返回
return Mouse;
}
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
const MouseTracker = props => {
// 高阶组件没有传递时 获取不到 age 属性
// 传递之后可以获取到了
console.log('mouseTracker', props)
return (
<div>
<h1>高阶组件</h1>
当前坐标是:{props.x}, {props.y}
</div>
)
}
// 调用高阶组件得到增强后的组件
const EnhancedMouse = withMouse(MouseTracker);
export default EnhancedMouse;
关于设置 displayName,是为了便于调试,因为通过高阶组件包装之后的组件名称都一样,不利于 通过 react developer 工具调试, 下面是官方推荐的方式
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
关于高阶组件 props 丢失问题
<HighRanking.HighHoc age={20}></HighRanking.HighHoc>
在使用高阶组件时,传递了 age 属性,但是在 MouseTracker 组件中获取不到,因为在 withMouse 组件中,没有继续往下传递 props 造成的,只需要继续往下传即可。
withMouse 中 mouse 组合中的render改成如下代码即可
render() {
// props 可以访问到 age属性
console.log('mouse', this.props)
return <WrappedComponent {...this.state} {...this.props} />;
}
完