先记住这个答案
mousedown 在按下鼠标键时就发出,mouseup 等释放时发出,click 是用户完成一次主激活后产生的事件。对普通按钮、链接和菜单选择,监听 click 更贴近动作语义,也能覆盖键盘激活;拖拽、绘画需要从按下开始跟踪,才考虑更底层的指针事件。不能把 click 机械说成“任何 mousedown 加任意 mouseup 一定触发”。
mousedown发生在按下瞬间mouseup发生在释放瞬间click表示完整激活动作- 键盘也可激活
click
按钮和拖拽的需求不一样
“保存”按钮只需要在用户完成激活时执行。拖动画布中的形状则需要从指针按下那一刻记录起点,持续跟踪移动,到释放时结束。两类交互不应该用同一个事件替代。
const save = document.querySelector('#save')
save.addEventListener('click', () => {
console.log('开始保存草稿') // 激活完成后才执行保存逻辑
})
const canvas = document.querySelector('#canvas')
canvas.addEventListener('pointerdown', event => {
console.log('拖动起点', event.clientX, event.clientY)
})原生按钮上的 click 可由鼠标、键盘等激活路径触发;pointerdown 适合鼠标、笔和触摸的统一指针模型。示例只显示拖拽起点,完整拖拽还需处理移动、释放和取消。
如果把“保存”绑定 mousedown,鼠标还没松开就执行,键盘用户也可能无法触发。这与按钮的预期激活语义不符。
不要假设简单固定事件序列
典型鼠标主键单击常见顺序是按下、释放、点击,但具体目标、设备以及指针是否移出元素都会影响点击是否成立。键盘激活按钮时可能有 click,却不先发生鼠标按下和释放。
原生双击还会产生两次点击再产生 dblclick。需要区分单击与双击时,应明确产品行为并处理单击动作已经执行的问题,而不是以为浏览器会自动延迟第一次 click。
pointerdown 也并非替换按钮 click 的通用方案。它把鼠标、触笔、触摸统一到一套指针事件里,适合连续手势;但一次触摸之后可能还会产生兼容的鼠标或点击事件。如果同一动作同时监听 pointerdown 和 click,要明确两者分别做什么,否则可能执行两遍。
完整拖拽通常还要监听 pointermove、pointerup 和 pointercancel,并考虑指针移出元素后的捕获。只在 mousedown 里记一个坐标,鼠标移走后若收不到释放事件,界面容易一直停在“拖动中”。
容易答错的地方
- 给按钮只监听
mousedown - 键盘激活没有鼠标按下事件,且动作会在释放前执行。
- 认为
click必定由本元素的按下和释放组成 - 合成点击、键盘激活及目标变化都可能让这个简化模型失效。
面试官还会怎么问?
拖拽为什么推荐 Pointer Events?
统一覆盖鼠标、触控笔和触摸,并提供 pointerId 等信息,适合持续跟踪。
右键会触发普通 click 吗?
普通 click 主要表示主按钮激活;右键菜单应监听 contextmenu,其他按钮可看 auxclick。
双击前会触发几次 click?
典型鼠标双击会先完成两次单击,再触发 dblclick;单击处理器可能已运行两次。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。