题目又名:简略弹窗、多弹窗、简单弹窗怎么做代码和状态的解耦。
关键字:react / modal
问题
理论业务中,不乏弹窗组件中蕴含大量简单的业务逻辑。如:
function Order() { // 省略上百行办法状态 const [visible,setVisible] = useState(false) const withModalState = useState<any>() return ( <Modal> <Input/> <Input/> <Select/> <Checkbox/> </Modal> ) }
甚至还有多弹窗的情景。如:
function Order() { // 省略上百行办法状态 const [visible1,setVisible1] = useState(false) const [visible2,setVisible2] = useState(false) const [visible3,setVisible3] = useState(false) const withModalState1 = useState<any>() const withModalState2 = useState<any>() const withModalState3 = useState<any>() // 省略 不懂多少 handlexx return ( <main> ... <Modal1></* 省略很多代码 */></Modal1> <Modal2></* 省略很多代码 */></Modal3> <Modal3></* 省略很多代码 */></Modal3> </main> ) }
十分的痛:
- 如果弹窗在解决完外部流程后,又还有返回值,这有又会有一大通的处理函数。
- 如果这些代码都写在一个文件中还是不太容易保护的。
而且随着业务的断增长,每次这么体验很差。
冀望的应用形式
因而有没有一种更贴近业务理论的计划。
让弹窗只专一于本人的外部事务,同时又能将控制权交给调用方呢。
或者说我就是不喜爱 Modal 代码堆在一起……
如下:
// Modal1.tsxexport function Modal1(props) return <Modal></* ... */></Modal>// 甚至能够将MOdal中的逻辑做的更聚合。通过2次封再导出给各方应用export const function Check_XXX_Window() {/* */ return open(Modal1)}export const function Check_XXX_By_Id_Window() { return open(Modal1)}export const function Check_XXX_Of_Ohter_Window() { return open(Modal1)}// Order.tsxfunction Order() { function xxHndanle { const expect = Check_XXX_Window(Modal1,args) // 调用办法,传入参数,取得预期值 ,实现1个流程 } return ( <main> ... // 不理论挂载 Modal 组件 </main> ) }
像这样拆散两者的代码,这样解决起来必定是清新很多的。
实现思路
实现的思路都是统一的。
- 创立占位符组件,放到利用的某处。
- 将相干状态集治理,并与Modal做好关联。
- 裸露控制权。
因而基于不同的状态治理计划,实现是多种多样的。置信很多大佬都本人外部封装过不少了。
然而在此基础上,我还想要3点。
- API应用简略,但也容许肯定配置。
- 返回值类型推导,除了帮我治理 close 和 open 还要让我用起来带提醒的。
- 无入侵性,不依赖框架以外的货色。
ez-modal-react
emm......苦于市面上找不到这类产品(感觉同类并不多……探讨的也不多?)
于是我本人开源了一个。回应上文实现思路,能够点击看代码,几百行而已。
并不是突发奇想而来,其实相干个性早就在企业外部是应用多年了。我也是受前辈和社区启发。
根本个性
- 基于Promise封装
- 返回值类型推导
- 没有入侵性,体积小。
应用画面
import EasyModal, { InnerModalProps } from 'ez-modal-react';+ interface IProps extends InnerModalProps<'fybe?'> /*传入返回值类型*/ {+ age: number;+ name: string;+ }export const InfoModal = EasyModal.create(+ (props: Props) => { return ( <Modal title="Hello" open={props.visible} onOk={() => {+ props.hide(); // warn 应有 1 个参数,但取得 0 个。 (property) hide: (result: "fybe?") => void ts(2554) }} onCancel={() => { props.hide(null); //safe hide 承受 null 作为参数。它兼具 hide resolve 两种性能。 }} > <h1>{props.age}</h1> </Modal> );});+ // warn 类型 "{ name: string; }" 中短少属性 "age",但类型 "ModalProps<Props, "fybe?">" 中须要该属性。EasyModal.show(InfoModal, { name: 'foo' }).then((resolve) => { console.log(resolve);+ //输入 "fybe?" });
也反对用 hook
import EasyModal, { useModal, InnerModalProps } from 'ez-modal-react';interface IProps extends InnerModalProps<'苏振华'>/* 指定返回值类型 */ { age: number; name: string;}export const Info = EasyModal.create((props: Props) => { const modal = useModal<Props>(); function handleOk(){ modal.hide(); // ts(2554) (property) hide: (result: "苏振华") => void ts(2554) } return <Modal open={modal.visible} onOk={handleOk} onCancel={modal.hide}></Modal>});EasyModal.show(Info,{age:18,}) // 短少属性 "age"
还有一些个性如反对配置 hide 弹窗时的默认行为。(我认为大多数状况下可能用不上)
export const Info = EasyModal.create((props: Props) => { const modal = useModal<Props>(); function handleOk(){ modal.hide(); + modal.resolve('苏振华') // 须要手动抛出胜利+ modal.remove() // 须要手动登记组件。可用于重复关上弹窗,然而不心愿状态被革除的场景。 } return <Modal open={modal.visible} onOk={handleOk} onCancel={modal.hide}></Modal>// Ohter.tsxEasyModal.open(Info, {},+ config:{+ resolveOnHide:false, // 默认为 true+ removeOnHide:false, // 默认为 true+ });
当然以上是针对弹窗内有简单业务场景的情况。
大部分场景都是调用方只在乎 open或close ,仅仅解耦代码这一项益处,就能够让代码变得清新。
如罕用的有展现类,设置类的弹窗,TS类型都用不上。
仓库
其余就不一一介绍了,次要的曾经说完了,想理解更多,能够看看仓库。github
Codesandbox Demo
Codesandbox是一个线上集成环境,能够间接关上玩玩。点击 Demo Link 返回
初衷
让弹窗应用更轻松。
包名 ez 结尾,是因为我DOTA在东南亚打多了,感觉该词特地贴切。
授之于鱼叉
GitHub仓库地址
:ez-modal-react
感觉有用帮我点个星\~\~\~ 感恩,有啥问题能够提出,看到会回复。如果有须要会继续保护该我的项目。