React 高阶HOC (一)

2022-08-08 13:01:19 浏览数 (1)

高阶组件

高阶组件 (HOC) 是 React 中用于重用组件逻辑的高级技术。HOC 本身并不是 React API 的一部分。它们是从 React 的组合性质中出现的一种模式。

高阶组件定义

根据官网介绍

高阶组件是一个接受一个组件并返回一个新的函数

代码语言:javascript复制
const myComponent = HOC(subComponent)

存在两个逻辑相似,页面功能相似的页面,可以使用高阶函数去减少相同相似的代码,共享方法,和生命周期钩子函数

用法与注意事项(官网):

1.高阶组件是参数为组件,返回值为新组件的函数。 2.HOC 不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC 通过将组件包装在容器组件中来组成新组件,HOC 是纯函数,没有副作用。 3.不要试图在 HOC 中修改组件原型 4.HOC 通常可以接收多个参数 4.不要在 render 方法中使用 HOC 5.务必复制静态方法 6.Refs 不会被传递,可使用React.forwardRef 解决

使用格式:

一般文件和方法名都是with开头


包装组件

普通包装

export 暴露
代码语言:javascript复制
import React, { Component } from 'react'

export default Class Wrap extends Component {
    render() {
        return (
            <div>{ this.props.name }</div>
        )
    }
}
import 包装
代码语言:javascript复制
 import Wrap from './Wrap';
 import withContainer from './HOC/withContainer'

 const userContainer = withContainer(Wrap);
 const userPage = () => {
     return (
        <div>
            <userContainer name={'BobMary'} />
        </div>
     )
 }
 

装饰器包装(只存在类class用法中)

代码语言:javascript复制
import React, { Component } from 'react'
import withContainer from './HOC/withContainer'

@withContainer
export default class Wrap extends Component {
     render() {
        return (
            <div>{ this.props.name }</div>
        )
    }
}

项目举例

项目需求

某个公司需要搬迁,需要系统采集登记已经搬迁的信息,包括:人员,物品,车辆。从A地区 搬迁到B地区。

需求分析

需要多个文件,实现的方式方法类似,展示的内容稍微不同,如果单独写每个文件,冗余代码较多,维护不便。

如果编写如下的代码,实现单个模块的逻辑,如果存在更细致的统计,那将复制粘贴出大量的相识相同的代码。

在假如,在搬迁的时候要求增加是谁负责某个模块,需要签名并实现流程化,那么这么多的模块都单独在增加,维护量和阅读量都非常的大

拓展( 应用场景)

  • 1 路由配置:对路由进行封装,针对复杂树形导航与头部导航交替路由;也用于未登录未授权的用户的拦截
  • 2 数据监控:加入埋点,分析数据
  • 3 数据校验:表单的统一校验
  • 4 数据异常处理:对报错数据进行处理,可以使用弹框提示,也可以进入埋点
  • 5 权限判断:类似路由,点击按钮时,对页面的权限进行验证,在返回对应的路由或者弹框
代码语言:javascript复制
// bad
import React, { Component} from 'react'
class GetGoodList extends Component {
    constructor() {
        this.state = {
            ...
        }
    }

    handleChangeCheck(e, index, id) {
       ...
    }

    handleMoveSome() {
        ...
    }

    render() {
        const { xxx } = this.state
        return (
            ...
            <span>car</span>
        )
    }
}
export default GetGoodList

如果要从人员,物品,车辆,分成三个文件独立维护,需要写大量重复的代码,因从我们需要将大部分逻辑代码提出来

HOC写法例子如下:

效果图:

代码语言:javascript复制
import React, { Component } from 'react'
import SuperList from '../components/list/SuperLIst'

function withMove (WrapComponent, preData) {
    return class MoveSomeToPlace extends Component {
        constructor(props) {
            super(props)
            this.needMoves = []
            this.state = { ...preData, hasMoved: []}
        }
    
        handleChangeCheck() {
            return (e, index, id) => {
                const { checked } = e.target
                const { userListShow } = this.state
                const position = this.needMoves.findIndex(e => e.id == id) 
                const isExist = position === -1
                if (checked &amp;&amp; isExist) {
                    this.needMoves.push(userListShow[index])
                } else if (!checked &amp;&amp; !isExist) {
                    this.needMoves.splice(position, 1)
                }
                userListShow[index].hasChecked = checked ? 'checked' : ''
                this.setState({
                    userListShow
                })
            }
          
        }
    
        handleMoveSome() {
            const data = [ ...this.needMoves ]
            this.setState({
                hasMoved: data
            })
        }
    
        render() {
            const { moveType, userListShow, hasMoved } = this.state
            return (
                <div className="c-stop-area">
                    <div className="need-move--left">
                        <SuperList lists={userListShow} needCheckbox
                            handleChangeCheck={this.handleChangeCheck()} />
                    </div>
                    <div>
                        <button className="c-btn" onClick={() => this.handleMoveSome()}>{moveType}</button>
                    </div>
                    <div className="has-moved--right">
                        <SuperList lists={hasMoved}
                            handleChangeCheck={this.handleChangeCheck()} />
                    </div>
                    <WrapComponent {...this.props}/>
                </div>
            )
        }
    }
}

export default withMove

三个不同的文件 ,数据和组件与之不同,但是完成的事相同,都是将A(左侧区域)的物品或人员通过勾选,入栈,在点击中间按钮进行移动(拷贝操作)最后呈现到B(右侧区域)

代码语言:javascript复制
// 物品 搬运,数据列表不同
import React, { Component} from 'react'
import goodList from '../../mock/good'
import withMove from '../../HOC/withMove'

const goodSource = {
    moveType: '搬运',
    userListShow: goodList
}
class GetGoodList extends Component {
    render() {
        return (<span>good</span>)
    }
}
export default withMove(GetGoodList, goodSource)

//=================================

// 人员 移动,数据列表不同
import React, { Component} from 'react'
import userList from '../../mock/user'
import withMove from '../../HOC/withMove'

const userSource = {
    moveType: '移动',
    userListShow: userList
}
class GetUserList extends Component {
    render() {
        return (<span>user</span>)
    }
}

export default withMove(GetUserList, userSource)

//=================================

// 汽车 启动,数据列表不同
import React, { Component } from 'react'
import carList from '../../mock/car'
import withMove from '../../HOC/withMove'

const carSource = {
    moveType: '启动',
    userListShow: carList
}

class GetCarList extends Component {
    render() {
        return (<span>car</span>)
    }
}

export default withMove(GetCarList, carSource)

持续更新,反向继承例子 与 ref使用

写的比较简单,有不足处,需要补充的地方欢迎大家留言,相互学习

0 人点赞