写在前面
写文章水平有限,已经快一年没写过了,越不写越不会写,索性尝试写一些和大家分享讨论一下
2022 年我从 Vue 切换到 React 开发,在这过去的一年多时间,我待过 2 个团队,毫无意外的都是 React + Ant Design。我相信这是国内绝大多数团队都有使用过的 UI 框架。当然国外的 MUI 也很棒。
modal 有哪些痛点
-
在没有统一使用 Provider 管理 Modal 的情况下, 我以及我的同事使用最多的方法就是在组件中导入antd Modal,然后使用 React.useState 定义一个 state 传递给 modal 的
visibleopen 属性。以受控的形式管理弹窗的显隐。并且还需要在onCancel
和onOk
回调中修改 state 来关闭弹窗。 -
通常打开一个弹窗都伴随着用户点击操作,开发者需要手动对触发器添加 onClick 事件。
-
antd Modal 提供了
footer
属性,假设我们的业务代码比较复杂,一股脑塞入 Modal children 会很臃肿,开发者不得不将其抽离出来。但是 footer 又和业务分离,不够内聚。导致我们需要将控制弹窗的开关透传下去。 -
接第 3 点,antd Modal 提供了
destroyOnClose
属性,表示关闭时销毁子元素。这里经常遇到一个问题是,即使我加了这个属性,但是封装的组件包含的 state,然后直接在 children 里直接消费,这个属性的作用就不大了。 -
antd 提供的输入组件都提供了受控和非受控能力,但是 Modal 的显隐却没有非受控设计。以至于开发者想 mount 组件时默认打开弹窗。这样的操作需要开发者二次封装或者设计。
-
拖拽弹窗,一般情况下 Modal 打开都是固定位置,但是有时候输入时遮挡了用户观察,虽然我们可以使用 Drawer 代替,但有时候我们还是希望有一个可拖动的 Modal,尽管 antd 提供了可拖拽 Demo,但是我阅读起来还是有些难理解。(这条可能是一个 feature。不属于痛点。
怎么解决呢
-
第一种方式是去 antd 官方 仓库创建一个 RFC 进行讨论,如果被采纳则可以发起一个 PR。
-
第二种方式就是二次开发, 所以有了这篇文章。
easy-antd-modal
它来了,我又重复造轮子了, github 仓库地址:github.com/Wxh16144/ea…
使用方式
import { Button } from 'antd';
import Modal from 'easy-antd-modal';
export default () => (
<Modal
title="easy-antd-modal"
trigger={<Button type="primary">Click Me</Button>}
>
I ❤️ antd
</Modal>
);
hook
为了解决上诉痛点 1,2,3,4,5 我封装了 useModalEnhanced hook 对弹窗的 props 进行了 HOC
这个 hook 不仅仅可以对 Modal 进行增强,还可以对 antd Drawer 封装同样的能力,以及 antd mobile 的 Mask, Modal, Popup, Dialog 组件都适用。我都进行了二次开发。
components
至于可拖动的弹窗,我依赖了 @dnd-kit/core 库实现了可拖拽功能组件 DragModal
社区好多组件都有一个 Provider ?,我也不例外,也加入了 EasyAntdModalProvider 组件。可以根据开发者喜好进行自定义 props 约定。
feature
- 所有 antd 支持的 props 都进行了透传,所以它支持 antd4 和 antd5
- 对 trigger 自动绑定 onClick 事件,open state 由内部维护。
- content(children) 增强,支持调用 close 关闭弹窗。
- 保留以上功能的情况下支持拖拽,类似 Windows 弹窗。
- 同样的能力可以应用在 antd-mobile 组件上。
- 长期维护,有足够的单元测试支撑。欢迎 PR。
具体文档/示例可以移步:wxh16144.github.io/easy-antd-m…
最后
欢迎大家进行讨论,分享大家在开发过程中遇到的问题以及对 antd 的吐槽。万一哪天被就被 antd 团队采纳了呢。
也希望大家可以尝试并讨论我二开的组件,npm install easy-antd-modal
。