应使用事件委托将监听层上提至列容器(.column),结合clientY与卡片位置动态判断悬停区域,避免直接绑定mouseenter导致的性能问题、漏判及drag/drop事件抑制。

在多栏目看板中,用事件委托实现卡片跨列“滑过”与“停留”的精准识别,核心不是监听每张卡片的 mouseenter,而是把事件捕获层上提至列容器(.column),再结合鼠标坐标与子元素位置动态判断——这样既避免大量重复绑定,又能稳定响应拖拽过程中的连续悬停行为。
为什么不能直接给每张卡片加 mouseenter?
卡片可能动态增删,频繁绑定/解绑影响性能;拖拽中鼠标快速掠过多个卡片时,mouseenter/mouseleave 触发不稳定,尤其在 gap 区域或卡片边缘容易漏判;更重要的是,原生 drag/drop 流程中,浏览器会抑制部分鼠标事件,默认不触发 mouseenter。
用 column 委托 + clientY 定位插入点
在列容器上监听 dragover(必须)和 mousemove(可选辅助),通过 event.clientY 与目标列内各卡片的 getBoundingClientRect() 对比,实时计算鼠标正对哪两张卡片之间,从而确定“停留区域”:
- 只在
dragover中做一次preventDefault(),保证 drop 可触发 - 调用
column.querySelectorAll('.card')获取当前列所有卡片节点 - 遍历卡片,用
rect.top + rect.height / 2算出每张卡片的垂直中线 - 当
clientY 时,即为插入该卡片之前 - 没匹配到任何卡片时,说明鼠标停在列底部空白区,插入末尾
视觉反馈靠 class 切换,不依赖 drag image
不要依赖 dataTransfer.setDragImage()(兼容性差、移动端失效),改用 CSS 配合 JS 控制样式:
- 给列容器添加临时 class,如
column--hovering,用 CSS 设置背景微调或边框高亮 - 在目标卡片上方插入一个带
class="drop-hint"的空 div,高度 2px,背景色突出,随鼠标移动实时重定位 - 离开列区域时,清除所有 hint 和 hover class,避免残留
防抖与状态锁定很关键
拖拽过程中 dragover 触发极频繁,不做节流会导致卡顿或误判:
- 用
requestAnimationFrame包裹位置判断逻辑,确保每帧最多执行一次 - 设置一个
isHovering标志位,进入列时设为 true,dragleave时延时 50ms 清除(防跨卡片抖动误判) - 只在
isHovering === true且当前列非源列时,才激活插入提示和位置计算

















