定义
高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。
具体而言,高阶组件是参数为组件,返回值为新组件的函数。
例子
有下面这样两个组件
import React, {Component} from 'react'
class Welcome extends Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentDidMount() {
this.setState({
username: 'LLL'
})
}
render() {
return (
<div>welcome {this.state.username}</div>
)
}
}
export default Welcom
import React, {Component} from 'react'
class Goodbye extends Component {
constructor(props) {
super(props);
this.state = {
username: ''
}
}
componentDidMount() {
this.setState({
username: 'LLL'
})
}
render() {
return (
<div>goodbye {this.state.username}</div>
)
}
}
export default Goodb
我们发现,这两个组件中存在大量的相似代码,因此,我们可以通过高阶组件(一个函数,且该函数接受一个组件作为参数,并返回一个新的组件)来解决这个问题
import React, { Component } from 'react';
export default (WrappedComponent) => {
class NewComponent extends Component {
constructor() {
super();
this.state = {
username: '',
};
}
componentWillMount() {
this.setState({
username: 'LLL',
});
}
render() {
return <WrappedComponent username={this.state.username} />;
}
}
return NewComponent;
这样我们就能简化Welcome组件和Goodbye组件。
import React, { Component } from 'react';
import wrapWithUsername from './wrapWithUsername';
class Welcome extends Component {
render() {
return (
<div>
welcome
{this.props.username}
</div>
);
}
}
Welcome = wrapWithUsername(Welcome);
export default Welcom
import React, { Component } from 'react';
import wrapWithUsername from './wrapWithUsername';
class Goodbye extends Component {
render() {
return (
<div>
goodbye
{this.props.username}
</div>
);
}
}
Goodbye = wrapWithUsername(Goodbye);
export default Goodby
本例中,高阶组件就是把username通过props传递给目标组件了。目标组件只管从props里面拿来用就好了。
应用
属性代理(Props Proxy)
可以说是对组件的包裹,在包裹的过程中对被包裹的组件做了点什么(props的处理,把基础组件和其他元素组合),然后返回,这就成了一个高阶组件。
1、props的处理
如withRouter
2、把基础组件和其他元素组合
出于操作样式、布局或其它的考虑,可以将 基础组件与其它组件包裹在一起。一些相对简单的用法也可以使用正常的父组件来实现,只是使用高阶组件可以获得更多的灵活性。也利于组件的抽象和复用。
export default (WrappedComponent) => {
class NewComponent extends Component {
constructor() {
super();
this.state = {
username: '',
};
}
componentWillMount() {
this.setState({
username: 'LLL',
});
}
render() {
return (
<div style={{background:'pink'}}>
<WrappedComponent username={this.state.username} />
</div>
);
}
}
return NewComponent;
}
arm框架中的createBundle组件就是很好的一个应用
反向继承 (Inheritance Inversion)
可以理解成是组装,和属性代理不同的是,反向继承是继承自基础组件,所有很自然,它可以直接获取基础组件的props,操作基础组件的state。
1、渲染劫持
所谓渲染劫持就是,高阶组件控制了基础组件渲染生成的结果,因为基础组件的渲染被控制,高阶组件就可以对它做点什么。。。比如:
(1)、看心情(根据条件),控制渲染的结果;
(2)、改变dom树的样式;
(3)、改变基础组件中一下被渲染元素的props;
(4)、操作dom树中的元素。
2、操作state
高阶组件可以读取、编辑和删除 基础组件 实例的 state,如果你需要,你也可以给它添加更多的 state。需要注意的是,这会搞乱基础组件 的 state,导致你可能会破坏某些东西。所以,要限制高阶组件读取或添加 state,添加 state 时应该放在单独的命名空间里,而不是和基础组件的 state 混在一起。
这个就是根据基础组件的state.name来决定要不要渲染。
export default (BaseComponent) => {
return class Enhancer extends BaseComponent{
render() {
return this.state.name === 'NNN' ? super.render() : null;
}
}
}
资料
https://react.docschina.org/docs/higher-order-components.html