React-封装命令式组件

669 阅读1分钟

以Antd的Modal为例子演示

第一种方式:封装在Hook(不建议,因为Hook一般是逻辑处理,不应该包含DOM)

// useModalHook.tsx, 文件后缀一定要是tsx
import React from "react";
import { render } from "react-dom";
import { Modal } from "antd";
import type { ModalProps } from "antd";

type TModalProps = Omit<ModalProps, "open">;

const container = document.createDocumentFragment();

const useModalHook = () => {
    const closeModal = () => {
        renderModal(false);
    };

    const renderModal = (open: boolean, modalOptions?: TModalProps) => {
        render(
            <Modal
                open={open}
                onCancel={closeModal}
                {...modalOptions}
                onOk={() => {
                    modalOptions?.onOk?.();
                    closeModal();
                }}
            >
                Hello World
            </Modal>,
            container
        );
    };

    return {
        renderModal,
        closeModal,
    };
};

export default useModalHook;

第二种方式:封装成class(推荐这种方式封装)

// popUpModal.tsx
import React from "react";
import { render } from "react-dom";
import { Modal } from "antd";
import type { ModalProps } from "antd";

type TModalProps = Omit<ModalProps, "open">;
type TPromiseResponse = {
    message: string;
    isSuccess: boolean;
};

const container = document.createDocumentFragment();

export default class PopUpModal {
    private open = false;

    private renderModal(modalOptions?: TModalProps) {
        render(
            <Modal open={this.open} {...modalOptions}>
                Hello World
            </Modal>,
            container
        );
    }

    private closeModal() {
        this.open = false;
        this.renderModal();
    }

    popUp() {
        return new Promise<TPromiseResponse>((resolve, reject) => {
            this.open = true;
            this.renderModal({
                title: "详情",
                okText: "确定",
                cancelText: "取消",
                onOk: () => {
                    this.closeModal();
                    resolve({
                        message: "成功",
                        isSuccess: true,
                    });
                },
                onCancel: () => {
                    this.closeModal();
                    reject({
                        message: "失败",
                        isSuccess: false,
                    });
                },
            });
        });
    }
}

函数组件中使用

import React from "react";
import useModalHook from "../useModalHook";
import { Button } from "antd";
import PopUpModal from "../popUpModal";

const Test = () => {
    const { renderModal } = useModalHook(); 
    const Modal = new PopUpModal();

    const modalOptions = {
        title: "详情",
        okText: "确定",
        cancelText: "取消",
    };

    const onclickButton = () => {
        Modal.popUp()
            .then((result) => console.log(result))
            .catch((error) => console.log(error));
    };

    return (
        <>
            <Button onClick={onclickButton}>打开class弹窗</Button>
            <Button onClick={() => renderModal(true, modalOptions)}>打开hook弹窗</Button>
        </>
    );
};

export default Test;

效果

  • Hook形式的Modal

image.png

  • class形式的Modal

image.png

触发Modal的onOk

image.png

触发Modal的onCancel

image.png