移动端设备上FullCalendar事件自定义删除按钮点击无响应问题
FullCalendar移动端自定义删除按钮点击不触发问题
问题场景
基于FullCalendar自定义事件视图,和默认视图逻辑基本一致,仅新增事件删除按钮。
初始实现代码如下:
eventDidMount: function(eventDidMountInfo) { var $deleteBtn = $(eventDidMountInfo.el).find('button') if(eventDidMountInfo.event.extendedProps.can_edit_event) { $deleteBtn.on( "click", function(argument) { deleteTimeSlot(calendar, eventDidMountInfo.event) }) } else { $deleteBtn.remove() } }, eventContent: function(info) { return { html: '<div class="fc-event-main-frame"><div class="fc-event-time">' + info.timeText + '<button type="button" class="btn-close float-end m-1" aria-label="Close"></button></div><div class="fc-event-title-container"><div class="fc-event-title fc-sticky">' + info.event.title + '</div></div></div>' }; }
该实现PC端可正常触发删除逻辑,移动端点击删除按钮无响应,初步判断和FullCalendar移动端长按交互特性相关。
根因分析
问题核心是FullCalendar移动端触控事件拦截:
- 组件默认会在事件容器上绑定
touchstart/touchend/touchmove系列事件,用于处理长按拖拽、事件点击跳转等交互,内部元素的事件冒泡会被容器拦截 - 移动端浏览器click事件存在300ms延迟,组件的触控事件响应优先级高于普通click事件,会直接吞掉绑定在子元素上的click回调
- 若事件容器默认渲染为
<a>标签,内部嵌套<button>属于非法HTML嵌套,部分移动端webkit内核浏览器会直接阻断子元素的事件响应
解决方案
按以下顺序调整即可解决:
- 调整事件绑定逻辑,同时适配移动端触控事件,阻止冒泡
修改eventDidMount内的绑定代码,同时绑定click和touchend事件,在回调中阻止事件冒泡和默认行为,避免事件被外层容器捕获:eventDidMount: function(eventDidMountInfo) { var $deleteBtn = $(eventDidMountInfo.el).find('button') if(eventDidMountInfo.event.extendedProps.can_edit_event) { const triggerDelete = function(e) { e.stopImmediatePropagation(); e.preventDefault(); deleteTimeSlot(calendar, eventDidMountInfo.event) } // 同时绑定桌面端click和移动端touchend事件 $deleteBtn.on("click touchend", triggerDelete) } else { $deleteBtn.remove() } }, - 添加CSS规则调整事件响应层级,避免容器拦截按钮事件
/* 提升删除按钮层级,单独开启事件响应 */ .fc-event .btn-close { position: relative; z-index: 99; pointer-events: auto; } /* 关闭事件容器本身的事件拦截,仅让内部交互元素响应事件 */ .fc-h-event { pointer-events: none; } .fc-h-event .fc-event-main, .fc-h-event .fc-event-main-frame, .fc-h-event .fc-event-time, .fc-h-event .fc-event-title-container { pointer-events: auto; } - 调整FullCalendar初始化参数,降低长按事件的拦截优先级
若业务场景不需要移动端拖拽调整事件时间,可直接关闭编辑能力,或拉长长按触发延迟,避免普通点击被长按逻辑抢占:const calendar = new FullCalendar.Calendar(calendarEl, { // 其他配置... editable: false, // 不需要拖拽修改事件时直接关闭 eventLongPressDelay: 10000, // 将长按触发阈值设为极大值,不触发长按拖拽逻辑 selectLongPressDelay: 10000 }) - 修复HTML嵌套问题
若上述方案仍存在兼容问题,将eventContent中的<button>标签替换为<span>标签模拟关闭按钮,避免<a>标签嵌套<button>的非法结构问题。
排查路径
- 用移动端远程调试工具选中删除按钮,监控点击时的事件触发顺序,确认事件是被外层容器拦截还是未成功绑定
- 临时注释FullCalendar配置中的
editable、eventClick相关配置,测试按钮点击是否恢复,确认是否为组件内置事件拦截导致 - 分别测试短按(<100ms)、长按(>500ms)按钮的响应差异,确认是否为长按事件逻辑抢占了普通点击
内容的提问来源于stack exchange,提问作者letz
相关产品推荐
相关产品推荐

