趣味理解:一个组件进了一个工厂,出来了就变成了带装备的组件,这个工厂就是高阶组件
- 高阶组件是一个函数,接受一个组件作为参数,返回一个新的组件
- 可作为装饰器使用
高阶组件有两种实现形式,属性代理和反向继承
- 属性代理: 高阶组件通过被包裹的React组件来操作props,实现对原组件props的增删改查
- 反向继承: 高阶组件继承于被包裹的React组件
先来说说属性代理
这是一个最简单的实现,也是最常见的一种声名高阶组件的方法
1 2 3 4 5 6 7 8 9
| import React,{Component} from 'react';
const MyContainer = (WraooedComponent) => { return class extends Component { render(){ return <WrappedComponent {...this.props} /> } } }
|
属性代理–操作props
属性代理可以对原组件的props进行增删改查,通常是查找和增加,删除和修改的话,需要考虑到不能破坏原组件
1 2 3 4 5 6 7 8 9 10
| function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { const newProps = { user: currentLoggedInUser } return <WrappedComponent {...this.props} {...newProps}/> } } }
|
属性代理–通过refs访问组件实例
可以通过ref回调的形式来访问组件实例,进而调用组件相关方法和其他操作
1 2 3 4 5 6 7 8 9 10 11 12 13
| function refsHOC(WrappedComponent) { return class RefsHOC extends React.Component { proc(wrappedComponentInstance) { wrappedComponentInstance.method() }
render() { const props = Object.assign({}, this.props, {ref: this.proc.bind(this)}) return <WrappedComponent {...props}/> } } }
|
属性代理–提取state
可以通过传入props和回调函数把state提取出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| function ppHOC(WrappedComponent) { return class PP extends React.Component { constructor(props) { super(props) this.state = { name: '' }
this.onNameChange = this.onNameChange.bind(this) } onNameChange(event) { this.setState({ name: event.target.value }) } render() { const newProps = { name: { value: this.state.name, onChange: this.onNameChange } } return <WrappedComponent {...this.props} {...newProps}/> } } }
@ppHOC class Example extends React.Component { render() { return <input name="name" {...this.props.name}/> } }
|
属性代理–包裹父级容器
为了封装样式,布局等目的,可以将组件用一个容器包裹起来,再不影响组件内部的同时改变了组件的布局,样式等
1 2 3 4 5 6 7 8 9 10 11
| function ppHOC(WrappedComponent) { return class PP extends React.Component { render() { return ( <div style={{display: 'block'}}> <WrappedComponent {...this.props}/> </div> ) } } }
|
继承反转
HOC继承了传入的组件,意味着可以访问到传入组件的state,props,生命周期和render方法,如果在HOC中定义了与传入组件同名方法,就必须手动通过super进行调用,通过完全操作传入组件的render方法返回的元素树,可以真正实现渲染劫持这种思想具有较强的入侵性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function ppHOC(WrappedComponent) { return class ExampleEnhance extends WrappedComponent { ... componentDidMount() { super.componentDidMount(); } componentWillUnmount() { super.componentWillUnmount(); } render() { ... return super.render(); } } }
|
参考传送门1
参考传送门2
参考传送门3