共计 3468 个字符,预计需要花费 9 分钟才能阅读完成。
题目又名:简略弹窗、多弹窗、简单弹窗怎么做代码和状态的解耦。
关键字: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.tsx
export 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.tsx
function 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.tsx
EasyModal.open(Info, {},
+ config:{
+ resolveOnHide:false, // 默认为 true
+ removeOnHide:false, // 默认为 true
+ }
);
当然以上是针对弹窗内有简单业务场景的情况。
大部分场景都是调用方只在乎 open 或 close,仅仅解耦代码这一项益处,就能够让代码变得清新。
如罕用的有展现类,设置类的弹窗,TS 类型都用不上。
仓库
其余就不一一介绍了,次要的曾经说完了,想理解更多,能够看看仓库。github
🎮 Codesandbox Demo
Codesandbox 是一个线上集成环境,能够间接关上玩玩。点击 Demo Link 返回
初衷
让弹窗应用更轻松。
包名 ez 结尾,是因为我 DOTA 在东南亚打多了,感觉该词特地贴切。
授之于鱼叉
GitHub 仓库地址
:ez-modal-react
感觉有用帮我点个星 \~\~\~ 感恩,有啥问题能够提出,看到会回复。如果有须要会继续保护该我的项目。