一、react 高阶组件 Higher-Order Components (简称为 HOC)
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。
HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
高阶函数:接受单个或多个函数作为参数并返回一个新函数的函数
高阶组件:接受单个或多个组件作为参数并返回一个新组件的函数
二、HOC 的种类
1. 属性代理
通过高阶组件将属性传递给被包装的原始组件,在原始组件中通过 this.props
操作属性
- 在组件中使用高阶组件
import React, { Component } from "react";
import HeightComponent from './pages/HeightComponent'
class App extends Component {
render() {
return (
<>
<HeightComponent a="a" />
</>
);
}
}
export default App;
- 高阶组件
定义高阶组件并在高阶组件中做通用逻辑处理
import React, { Component } from "react";
// 定义高阶组件
const HocPropsProxy = (TargetComponent) => {
// 返回容器组件
return class Enhance extends Component {
constructor(props) {
super(props);
this.state = {
b: "b",
};
}
render() {
return (
<>
<TargetComponent {...this.props} {...this.state} />
</>
);
}
};
};
// 定义原始组件
class Test extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<>
<div>
<div>hello world</div>
<div>a: {this.props.a}</div>
<div>b: {this.props.b}</div>
</div>
</>
);
}
}
// 使用高阶组件包装原始组件
export default HocPropsProxy(Test);
2. 反向继承
在高阶组件中,让容器组件继承原始组件
- 在组件中使用高阶组件
import React, { Component } from "react";
import HeightComponent from './pages/HeightComponent'
class App extends Component {
render() {
return (
<>
<HeightComponent a="a" />
</>
);
}
}
export default App;
- 定义高阶组件并在高阶组件中做通用逻辑处理
import React, { Component } from "react";
// 定义高阶组件
const HocPropsProxy = (TargetComponent) => {
// 返回容器组件
return class Enhance extends TargetComponent {
constructor(props) {
super(props);
this.state = {
b: "b",
};
}
render() {
return super.render()
}
};
};
// 定义原始组件
class Test extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<>
<div>
<div>hello world</div>
<div>a: {this.props.a}</div> {/* 来自继承 */}
<div>b: {this.state.b}</div>
</div>
</>
);
}
}
// 使用高阶组件包装原始组件
export default HocPropsProxy(Test);
三、HOC 常用示例
- redux 中的 connect
- react-router 中的 withRouter
四、高阶组件的拓展示例(分离通用样式和通用模板)
import React, { Component } from "react";
import styled from "styled-components";
// 添加公共样式
const Wrapper = styled.div`
height: 100vh;
width: 94%;
margin-left: 3%;
font-size: 24px;
background: #f3f3f3;
color: #666;
`;
// 定义高阶组件
const CommonCssWrapper = (TargetComponent) => {
// 返回容器组件
return class Enhance extends Component {
render() {
return (
<>
<Wrapper>
<h1>react 高阶组件</h1> {/* 添加模板内容 */}
<TargetComponent />
</Wrapper>
</>
);
}
};
};
// 定义原始组件
class Test extends Component {
render() {
return (
<>
<div>
<div>hello world</div>
</div>
</>
);
}
}
// 使用高阶组件包装原始组件
export default CommonCssWrapper(Test);
五、HOC 注意事项
1. 不能在无状态组件(函数类型组件)上使用 ref 属性
因为无状态组件没有实例
2. refs 属性不能透传
如果将 ref 添加到 HOC 的返回组件中,那么 ref 引用指向容器组件,而不是被包装的原始组件
4. 不要在 render 渲染方法中使用高阶组件
因为每次 render 函数在执行时,都会卸载和重新加载高阶组件,会造成状态丢失
5. 静态方法丢失
因为原始组件被包裹于一个容器组件内,所以高阶组件最终返回的组件没有原始组件的静态方法
但是可以通过 hoist-non-react-statics 脚本库做处理,实现静态方法拷贝
6. 不要以任何方式改变原始组件
网友评论