React高阶组件概述
- 高阶组件是React中一个很重要且比较复杂的概念,高阶组件在很多第三方库(如Redux)中都被经常使用,在项目中用好高阶组件,可以显著提高代码质量。
高阶函数的基本概念
- 函数可以作为参数被传递
setTimeout(() => {
console.log('1')
}, 1000)
- 函数可以作为返回值输出
foo = (x) => {
return function () {
return x
}
}
高阶组件的基本概念
- 高阶组件就是接受一个组件作为参数并返回一个新组件的函数。
- 高阶组件是一个函数,并不是组件。
为什么需要高阶组件?
- 多个组件都需要某个相同功能,使用高阶组件减少重复实现。
- 重复是优秀系统设计的大敌
- 高阶组件示例: react-redux 中的connect
export default connect(maoStateToProps, mapDispatchToProps)(Header)
高阶组件的实现
编写高阶组件
使用方法一:
- 实现一个普通组件
import React from 'react'
export default class Start extends React.Component {
render () {
return (
<div>组件A</div>
)
}
}
- 将普通组件使用函数包裹起来
import React from 'react'
function A (WrappedComponent) {
return class Start extends React.Component {
render () {
return (
<div>
<div>这是组件A</div>
<WrappedComponent />
</div>
)
}
}
}
export default A
- 使用高阶组件
import React from 'react'
import a from './A'
class B extends React.Component {
render () {
return (
<div>这是组件B</div>
)
}
}
export default a(B)
使用方法二:类装饰器
import React from 'react'
import a from './A'
@a
class B extends React.Component {
render () {
return (
<div>这是组件B-</div>
)
}
}
export default B
高阶组件应用
代理方式的高阶组件
返回的新组件类直接继承React.Component 类,新组件扮演的角色传入参数组件的一个代理,在新组件的render函数中,被包裹组件渲染出来,除了高阶组件自己要做得工作,其余功能全都转手给了被包裹的组件。
- 操作props
高阶组件能改变包裹组件的props,可以做任何的读取、编辑、删除props的一系列操作,甚至可以在高阶组件中自定义事件,然后通过props传递下去。
// A.js
import React from 'react'
function A (WrappedComponent) {
return class Start extends React.Component {
render () {
return (
<div>
<div>这是组件A</div>
{this.props.name}
<WrappedComponent {...this.props} age="18" />
</div>
)
}
}
}
export default A
// B.js
import React from 'react'
import a from './A'
@a
class B extends React.Component {
render () {
return (
<div>
<div>这是组件B:</div>
<p>我的名字叫:{this.props.name}</p>
<p>我的年龄是:{this.props.age}</p>
</div>
)
}
}
export default B
// C.js
import React from 'react'
class C extends React.Component {
render () {
return (
<div>组件C</div>
)
}
}
export default C
// D.js
import React from 'react'
import A from './A'
import B from './B'
import C from './C'
class D extends React.Component {
render () {
return (
<div>
<A />
<B name='张三' />
<C />
<div>这是组件D</div>
</div>
)
}
}
export default D
- 访问ref
ref可以自由的操作被包裹组件的元素
注意:(ref属性非常容易出问题,不推荐使用)
// A.js
import React from 'react'
function A (WrappedComponent) {
return class Start extends React.Component {
refTest (instance) {
instance.getName && alert(instance.getName())
}
render () {
const { age, ...otherProps } = this.props
return (
<div>
<div>这是组件A:</div>
{this.props.name}
<WrappedComponent {...otherProps} sex='A组件' ref={this.refTest.bind(this)} />
</div>
)
}
}
}
export default A
// C.js
import React from 'react'
import a from './A'
@a
class C extends React.Component {
getName () {
return '我是C组件'
}
render () {
return (
<div>组件C</div>
)
}
}
export default C
- 抽取状态
// A.js
import React from 'react'
function A (WrappedComponent) {
return class Start extends React.Component {
state = { value: '' }
inputHandle = (e) => {
let value = e.target.value
this.setState({ value })
}
render () {
const newProps = {
value: this.state.value,
onInput: this.inputHandle
}
return (
<div>
<div>这是组件A:{this.state.value}</div>
<WrappedComponent {...newProps} />
</div>
)
}
}
}
export default A
// B.js
import React from 'react'
import a from './A'
@a
class B extends React.Component {
render () {
return (
<div>
<div>这是组件B:{this.props.value}</div>
<input {...this.props} />
</div>
)
}
}
export default B
- 包装组件
继承方式的高阶组件
- 采用继承关联作为参数的组件和返回的组件,假如传入的组件参数是WrappedComponent,那么返回的组件就直接继承自WrappedComponent
export default () => WrappedComponent => class A extends WrappedComponent {
render () {
const { user, otherProps } = this.props
this.props = otherProps
return super.render()
}
}
-
操纵porps
-
操纵 生命周期函数