React@16.x(10)HOC高阶组件和横切关注点

1,什么是HOC

  • HOF:Heighter-Order Function。高阶函数,以函数为参数并返回一个函数。
  • HOC:Higher-Order Components。高阶组件,以组件为参数并返回一个组件。

2,什么是横切关注点

2.1,简单理解

在系统中横跨了多个模块或组件的,需要考虑的一些特定逻辑或领域(关注点)。它们和业务逻辑相独立,但在系统中多个部分重复出现。

这些关注点,都属于辅助功能,服务于核心功能–>业务逻辑。

对前端来说,常见的:

  • 日志记录。在多个位置都需要记录信息,以便于调试和监控。
  • 异常处理。在多个位置都需要捕获和处理异常。
  • 依赖注入。可以管理组件之间的依赖关系,比如在多个位置都需要组件的实例。
  • 状态管理。不多赘述。
  • 国际化。不多赘述。

2.2,常见解决方式

Vue 中的组件封装,mixin、hooks(Vue3)、自定义指令、状态管理,路由守卫都属于解决该问题的范畴。

React 中的组件封装,HOC,hooks,Context,状态管理也属于解决该问题的范畴。

一些设计模式:装饰器模式,观察者模式,责任链模式(处理审批)。

3,HOC 举例

React 中,通常会以 src/HOC 创建目录,文件名以 with 开头

使用 React16 进行开发离不开 HOC,无论是第3方库还是日常开发。下面只是简单举例,后面的文章也会遇到 HOC 的使用。

3.1,全局功能

比如,日志记录:

import { Component } from "react";

export default function withLog(Comp) {
    return class LogWrapper extends Component {
        componentDidMount() {
            console.log(`${Comp.name}组件被创建了`);
        }
        componentWillUnmount() {
            console.log(`${Comp.name}组件被销毁了`);
        }
        render() {
            return <Comp {...this.props} />;
        }
    };
}

使用

import HelloWorld from "./components/HelloWorld";
import withLog from "./HOC/withLog";

const Alog = withLog(HelloWorld)

因为是函数,所以可嵌套来增加多个额外功能。

const ResultComp = withLogin(withLog(CompA))

3.2,小范围使用

比如生成遍历循环的选项。

import { Component } from "react";
export default function withDataGroup(Comp) {
    return class DataGroupWrapper extends Component {
        static defaultProps = {
            datas: [],
        };

        render() {
            const comps = this.props.datas.map((it) => <Comp key={it.value} info={it} {...this.props} />);
            return <>{comps}</>;
        }
    };
}

Select 组件。保持源数据 data 数据结构一致时,checkbox 组件也可以使用 withDataGroup

import { Component } from "react";
import withDataGroup from "./HOC/withDataGroup";

class Option extends Component {
    render() {
        return <option value={this.props.info.value}>{this.props.info.text}</option>;
    }
}

const OptGroup = withDataGroup(Option);

export default class Select extends Component {
    render() {
        return (
            <select
                value={this.props.value}
                onChange={(e) => {this.props.onChange?.(e.target.value);}}
            >
                <OptGroup {...this.props}></OptGroup>
            </select>
        );
    }
}

使用

import React, { Component } from "react";
import Select from "./components/Select";

const datas = [
    { value: "football", text: "足球" },
    { value: "basketball", text: "篮球" },
    { value: "movie", text: "电影" },
];

export default class App extends Component {
    state = {
        value: "",
        datas,
    };
    handleChange = (value, name, e) => {
        this.setState({
            value,
        });
    };
    render() {
        return (
            <>
                <div>{this.state.value}</div>
                <Select {...this.state} onChange={this.handleChange} />
            </>
        );
    }
}

4,HOC 使用注意点

4.1,不要在 render 中使用

因为这样每次都会创建新的组件,效率低而且状态每次都会重置。

4.2,不要在高阶组件内部修改传入的组件

高阶组件内部,只应该增加功能。如果修改了原组件,会导致代码逻辑混乱,而且这种情况,逻辑写到原组件更合理。

4.3,只做一件事

一般只做一件事。这样代码比较简洁,原组件也方便扩展其他功能。


以上。

  • 36
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

下雪天的夏风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值