React有这样两种组件设计模式,高阶组件和函数式组件。高阶组件是将需要复用的逻辑提取到一个函数中,再去处理不同组件。函数作为子组件,是使用子组件来复用逻辑,然后从父组件传入不同内容。
我们来看下如何使用:
一、高阶组件
高阶组件是一个函数,它接受一个组件,返回一个新组件,可以提供可复用的功能。使用方法见下图:
// withToolTip.js
import React from 'react'
const withToolTip = (Component) => {
class HOC extends React.Component {
state= {
showToolTip: false,
content: ''
}
handleOver =(ev)=> this.setState({showToolTip: true, content: ev.target.innerText})
handleOut = (ev)=> this.setState({showToolTip: false, content: ''})
render(){
return (
<div onMouseOver={this.handleOver} onMouseOut={this.handleOut}>
<Component action={this.state} />
</div>
)
}
}
return HOC
}
export default withToolTip;
// ItemA.jsx
import React, {Component} from 'react';
import withToolTip from './withToolTip'
const ItemA = (props) => {
return (
<div>
<button type="btn">ToolTipA</button>
{props.action.showToolTip && (
<span>
{props.action.content}
</span>
)}
</div>
)
}
export default withToolTip(ItemA);
// ItemB.jsx
import React, { Component } from 'react';
import withToolTip from './withToolTip';
const ItemA = (props) => {
return (
<div>
<button type="btn">ToolTipB</button>
{props.action.showToolTip && (
<span>
{props.action.content}
</span>
)}
</div>
)
}
export default withToolTip(ItemB);
// App.js
import React, {PureComponent} from 'react';
import ItemA from './component/hoc/itemA';
import ItemB from './component/hoc/itemB';
class App extends PureComponent {
constructor(props){
super(props);
this.state = {
listData: [
{
id: 1,
name: 'name1'
},
{
id: 2,
name: 'name2'
}
]
}
...
}
render(){
return (
<>
<ItemA />
<ItemB />
</>
)
}
}
export default App;
总结一下例子中的基本用法:
- 父组件App引入两个子组件——ItemA和ItemB。
- ItemA和ItemB分别import withToolTip,并将组件ItemA/B作为参数返回新函数withToolTip(ItemA/B)。
- 将可复用的功能写在withToolTip函数中:定义方法名为withToolTip,将Component作为参数,返回withToolTip方法。在方法内部,定义类组件HOC并返回。在类组件HOC中定义state和渲染组件。
二、函数作为子组件
函数作为子组件,是使用子组件处理复用逻辑,然后从父组件传入不同内容。基本用法是:
- 定义子组件:
render(){
return (
<div>{this.props.render(this.state)}</div>
)
}
- 使用函数作为Props
<RenderPropComponent render = { (state)=>(
<div>content</div>
)} />
接下来,我们将上文高阶组件的例子改造成函数作为子组件的使用方式:
- withToolTip.js文件中,去掉const withToolTip = (Component) => {}一层;并且将<Component action={this.state} />替换为{this.props.render(this.state)}
- 新建ItemC.jsx组件,这里和ItemA/B的区别主要是:
在组件内,直接使用withToolTip组件,并将页面结构放在render中;
将props.action.xxx的props.action去掉;
直接返回ItemC组件。
import React, {Component} from 'react';
import withToolTip from './withToolTip';
const ItemC = (props) => {
return (
<div>
<WithToolTip render= {
<div>
<button type="btn">ToolTipA</button>
{showToolTip && (
<span>{content}</span>
)}
</div>
} />
</div>
);
}
export default ItemC;
其中,引用<WithToolTip />组件部分,也可以使用下面的写法:
<WithToolTip>
{ (showToolTip, content)=>(
<div>
<button type="btn">ToolTipA</button>
{showToolTip && (
<span>{content}</span>
)}
</div>
) }
</WithToolTip>
- withToolTip.js文件修改,也要去掉const withToolTip=(Component)=>{}一层,将HOC改为WithToolTip;去掉return HOC;并且将withToolTip大写,如下:
import React from 'react'
class WithToolTip extends React.Component {
state= {
showToolTip: false,
content: ''
}
handleOver =(ev)=> this.setState({showToolTip: true, content: ev.target.innerText})
handleOut = (ev)=> this.setState({showToolTip: false, content: ''})
render(){
return (
<div onMouseOver={this.handleOver} onMouseOut={this.handleOut}>
<Component action={this.state} />
</div>
)
}
}
export default WithToolTip;
网友评论