前言
一个项目中往往会包含很多相似的组件,既然组件基本相似,我们为什么不能像定义函数一样将其也定义成一种方法,我们调用这个方法,根据我们传入的参数返回给我们需要的组件,于是便涉及到了本文内容:高阶组件
一、前篇
我们需要两个组件,分别显示奇数和偶数,正常思路如下:
import React,{Component} from 'react'
class H1 extends Component{
constructor(props){
super(props)
this.state={
arr:[]
}
}
render(){
console.log(this.state.arr)
return(
<div>
<ul>
<p>H1</p>
{this.state.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})}
</ul>
</div>
)
}
componentDidMount(){
var {arr}=this.props
this.setState(
{
arr:arr.filter((item,index)=>{
return item%2==0
})
}
)
}
}
class H2 extends Component{
constructor(props){
super(props)
this.state={
arr:[]
}
}
render(){
console.log(this.state.arr)
return(
<div>
<ul>
<p>H2</p>
{this.state.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})}
</ul>
</div>
)
}
componentDidMount(){
var {arr}=this.props
this.setState(
{
arr:arr.filter((item,index)=>{
return item%2==1
})
}
)
}
}
class App extends Component{
constructor(props){
super(props)
this.state={
arr:[1,2,3,4,5,6,7,8,9],
}
}
render(){
return(
<div>
<H1 arr={this.state.arr}></H1>
<H2 arr={this.state.arr}></H2>
</div>
)
}
}
export default App;
不难发现,H1,H2两个组件除了名字和数组求法,其他一摸一样。这让我们不由得想到了函数,为了减少代码量,提高编码效率,我们可以封装一个函数,根据传入的参数,返回给我们组件。
二、高阶组件
高阶组件:用函数包装一个组件并可以生成新的组件。
高阶组件的意义:
1.重复利用代码,提取公共部分逻辑,利用高阶组件返回。
2.修改react组件行为
高阶组件实现方式:
1.代理方式
2.继承方式
代理方式应用场景:
1.操纵props
2.访问ref
3.抽离状态
4.包装组件
我们要写的是一个可以返回一个新的组件的函数,所以基本框架如下:
function H(WrapComponent) {
return class NewComponent extends Component{
}
}
既然里面返回的是一个新的组件,里面的内容和我们平时写的也就没什么区别:
function H(WrapComponent) {
return class NewComponent extends Component{
constructor(props){
super(props)
}
render(){
return(
<div></div>
)
}
componentDidMount(){
}
}
}
重点来了,高阶组件视图部分写法:
这里传递的arr是传递给新生成的(返回的)组件,给他们传递处理后的数据,然后由他们自身进行渲染。
到此,我们的H1,和H2就可以被H()函数封装如下:
H1=H(H1)
H2=H(H2)
然后就是函数中的逻辑,这里我们要区别两种组件的计算,传入参数boolean,如果值是true,做取偶数操作,否则做取奇数操作,函数如下:
function H(WrapComponent,boolean) {
return class NewComponent extends Component{
constructor(props){
super(props)
this.state={
newArr:[]
}
}
render(){
return(
<div>
<WrapComponent arr={this.state.newArr}></WrapComponent>
</div>
)
}
componentDidMount(){
var {arr}=this.props
if(boolean){
arr=arr.filter((item,index)=>{
return item%2==0
})
}
else {
arr=arr.filter((item,index)=>{
return item%2==1
})
}
this.setState({
newArr:arr
})
}
}
}
相应的H1、H2调用函数时也要传入boolean参数:
H1=H(H1,true)
H2=H(H2,false)
然后因为在H函数中已经定义了我们需要的逻辑,所以,H1、H2组件中逻辑部分可以删掉
最终App.js如下:
import React,{Component} from 'react'
function H(WrapComponent,boolean) {
return class NewComponent extends Component{
constructor(props){
super(props)
this.state={
newArr:[]
}
}
render(){
return(
<div>
<WrapComponent arr={this.state.newArr}></WrapComponent>
</div>
)
}
componentDidMount(){
var {arr}=this.props
if(boolean){
arr=arr.filter((item,index)=>{
return item%2==0
})
}
else {
arr=arr.filter((item,index)=>{
return item%2==1
})
}
this.setState({
newArr:arr
})
}
}
}
class H1 extends Component{
constructor(props){
super(props)
}
render(){
return(
<div>
<ul>
<p>H1</p>
{this.props.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})}
</ul>
</div>
)
}
}
class H2 extends Component{
constructor(props){
super(props)
}
render(){
return(
<div>
<ul>
<p>H2</p>
{this.props.arr.map((item,index)=>{
return <li key={index}>{item}</li>
})}
</ul>
</div>
)
}
}
H1=H(H1,true)
H2=H(H2,false)
class App extends Component{
constructor(props){
super(props)
this.state={
arr:[1,2,3,4,5,6,7,8,9],
}
}
render(){
return(
<div>
<H1 arr={this.state.arr}></H1>
<H2 arr={this.state.arr}></H2>
</div>
)
}
}
export default App;
结果: