本篇简单实现antdv同时弹多个弹窗
起因
今天听到产品给同事提了个需求,有个表格原本加了行事件,点击该行会打开一个弹窗,之前只能同时打开一个弹窗,现在需要同时打开多个。
分析
这个弹窗挺复杂的,之前专门有个弹窗的组件绑定在模版跟路径下,通过点击行来切换这个弹窗的显隐。
本来没啥大问题,但是现在要同时弹多个弹窗的话就不够用了,因为dom只有一个。
思路
- 使用动态弹窗。
antdv官网提供了API,可以使用Modal.info / Modal.success / Modal.error / Modal.warning / Modal.confirm几个方法来快速创建弹窗。
伪代码如下:
1 2 3 4 5 6 7 8 9
| const OpenModal = (key: string) => { Modal.confirm({ content: createVNode(createVNode('div', { class: 'content' }, key)), title: 'Modal', onOk() {}, onCancel() { }, }); };
|
看起来很简单,但是测试时却出现了问题,因为Modal组件自带遮罩,第一个弹窗出现后,因为遮罩阻挡,第二个点击事件无法触发。
- 去掉遮罩
根据Modal组件文档,可以传入mask属性来移除遮罩,但实际操作时发现,除了遮罩层,还有一个dialog的节点占满了屏幕,也会阻挡第二次点击事件。还好组件文档也相应提供了一个wrapClassName属性,我们可以通过自定义类名来自定义这个节点。
伪代码如下:
1 2 3 4 5 6 7 8 9 10
| const OpenModal = (key: string) => { Modal.confirm({ mask: false, wrapClassName: `test-modal`, content: createVNode(createVNode('div', { class: 'content' }, key)), title: 'Modal', onOk() {}, onCancel() {}, }); };
|
1 2 3 4 5 6 7 8 9 10 11
| .test-modal { width: fit-content; height: fit-content; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); top: 30%; left: 30%;
.ant-modal { top: 0; } }
|
其实到这本篇就算结束了,但是多次出发点击事件的时候,多个弹窗整整齐齐堆在一起,要不是有打开动画,还以为只开了一个弹窗呢。
- 增加位置偏移
提供一个简单的实现,上文中已经给弹窗增加了top和left属性,我们假设每打开一个新弹窗,相对前一个弹窗向右/向下各便宜40px。
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let num = 0;
const OpenModal = (key: string) => { Modal.confirm({ mask: false, wrapClassName: `test-modal test-modal-${num}`, content: h(h('div', { class: 'content' }, key)), title: 'Modal', onOk() {}, onCancel() { num--; }, }); num++; };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| .test-modal { width: fit-content; height: fit-content; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); top: 30%; left: 30%;
.ant-modal { top: 0; } }
@iterations: 5; .generate-classes(@i) when (@i <= @iterations) { .test-modal-@{i} { top: calc(30% + (40px * @i)); left: calc(30% + (40px * @i)); } .generate-classes(@i + 1); } .generate-classes(0);
|
最终效果

后话
当然,到这一步需求还没完,还缺一个手动拖拽,这个比较麻烦,有空再写。