如何避免ng-bootstrap的ngbModal组件内的按键绑定事件冒泡?
问题根因
该现象并非事件冒泡导致,而是回车键触发时序与ngbModal默认的焦点回退逻辑共同作用的结果:
当你在关闭按钮上按下回车键时,keydown/keypress阶段会先执行关闭逻辑,模态弹窗销毁后ngbModal会自动将焦点返回到触发弹窗的Open元素上;等事件流转到keyup阶段时,焦点已经落在Open元素上,因此你绑定的keyup.enter事件会被触发,导致弹窗重复打开。你之前尝试的阻止冒泡手段针对的是同元素的事件传递,自然不会生效。
可行解决方案
方案1(最优,改动最小):将触发事件从keyup改为keydown
keydown事件在按键按下的第一时间触发,此时焦点还未发生转移,不会出现跨元素触发的问题。修正后的触发元素代码如下:
<div (keydown.enter)="openModal($event)" (keydown.space)="openModal($event)" (click)="openModal($event)" role="button" tabindex="0" > Open Modal </div>
注:你原有的触发代码存在语法错误,
(keyup.space)绑定的属性值缺少闭合双引号,已在上述代码中修正。
方案2:增加模态打开状态锁
如果业务要求必须使用keyup事件触发,可以新增状态变量避免短时间内重复打开弹窗:
// 组件类中新增状态 isModalOpened = false; openModal(e: Event) { if (this.isModalOpened) return; this.isModalOpened = true; const modalRef = this.modalService.open(/* 你的模态组件 */); // 模态关闭后延迟解锁,避开keyup事件的触发时序 modalRef.closed.subscribe(() => { setTimeout(() => this.isModalOpened = false, 150); }) }
方案3:拦截关闭按钮的回车键事件
在关闭按钮上绑定keydown.enter事件,阻止事件默认行为和传播:
<button (keydown.enter)="$event.preventDefault(); $event.stopPropagation(); closeModal()"> Close </button>
ADA规范补充提示
你使用div作为交互触发按钮,必须补充role="button"和tabindex="0"属性,否则屏幕阅读器无法识别该元素为可交互按钮,也无法通过键盘Tab键聚焦,不符合ADA规范要求,上述方案1的代码中已补充相关属性。
内容的提问来源于stack exchange,提问作者Mike Gmez
相关产品推荐
相关产品推荐

