HOC : higher order component
HOC是一个纯函数,没有副作用
HOC是参数为组件,返回值为新组件的函数。组件是将props转换为UI,而高阶组件是将组件转换为另一个组件,但是不修改原组件。
例如:入参是一个组件,出参也是一个组件
function(componentA){
return componentB
}
作用:
- 抽离重复代码,实现组件的复用
- 条件渲染,渲染拦截
- 拦截组件的生命周期
利用HOC进行属性代码修改
- 修改参数,props
function HOC(WrappedComponent) {
const newProps = { type: "HOC" };
return props => <WrappedComponent {...props} {...newProps} />;
}
class类的写法
function HOC(WrappedComponent) {
return class extends React.Component {
render() {
const newProps = { type: "HOC" };
return <WrappedComponent {...this.props} {...newProps} />;
}
};
}
- 修改state
function HOC(WrappedComponent) {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
};
this.onChange = this.onChange.bind(this);
}
onChange = (e) => {
this.setState({
name: e.target.value,
});
};
render() {
const newProps = {
name: this.state.name,
onChange: this.onChange,
};
return <WrappedComponent {...this.props} {...newProps} />;
}
};
}
class Example extends React.Component{
render() {
return <input name {...this.props.name} />
}
}
- 条件渲染
function HOC(WrappedComponent) {
return props =>
props.isShow ? WrappedComponent : <div>empty</div>;
}
- 外部逻辑的封装
function HOC(WrappedComponent) {
return (
<div>
<p>Study</p>
<WrappedComponent></WrappedComponent>
</div>
);
}
反向继承
function HOC(WrappedComponent) {
return class extends WrappedComponent{
render(){
return super.render()
}
};
}
- 可以访问到props state
- 实现所谓生命周期的拦截
function HOC(WrappedComponent) {
const didMount = WrappedComponent.prototype.componentDidMount;
return class extends WrappedComponent{
async componentDidMount(){
if(didMount){
await didMount.apply(this)
}
}
render(){
return super.render()
}
};
}
- 进行修改react树
function HOC(WrappedComponent) {
return class extends WrappedComponent{
render(){
const tree = super.render()
const newProps = {}
if(tree && tree.type === "input"){
newProps.value = "inputTest"
}
const props = {
...tree.props,
...newProps
}
const newTree = React.cloneElement(tree, props, tree.props.children)
return newTree
}
};
}
- 计算组件的渲染时间
function withTiming(WrappedComponent) {
let start,end
return class extends WrappedComponent{
constructor(props) {
super(props)
start = new Date().getTime()
}
componentDidMount(){
if(super.componentDidMount){
super.componentDidMount()
}
end = new Date().getTime()
console.log(end-start)
}
};
}
属性代理和反向继承对比
- 属性代理:外 --> 内,传递props
- 反向继承:内 --> 外,render、props、state