RxJS拖拽功能疑问:Chrome中mousedown触发drag事件的原因?
解决RxJS拖拽实现中Chrome下mousedown立即触发drag的问题
嘿,这个问题我之前也碰到过!其实不是RxJS的锅,是Chrome浏览器的一个小特性——当你触发mousedown事件时,哪怕鼠标完全没动,Chrome也会立即派发一个mousemove事件,这就导致你的drag流因为take(1)的存在,在mousedown瞬间就被触发了。
问题代码分析
你原来的drag流逻辑是:
const drag = down.switchMap(() => move.takeUntil(up).take(1));
这里的take(1)会在move流的第一个事件触发时就完成整个流,而Chrome刚好在mousedown后立刻送了一个无位移的mousemove事件,所以drag就提前触发了。
解决方案:过滤无位移的mousemove事件
我们可以记录mousedown时的鼠标坐标,然后在mousemove事件里过滤掉和初始坐标完全一致的事件,只保留真正有位移的移动事件。修改后的代码如下:
// 记录mousedown时的坐标 const down = Rx.Observable.fromEvent(document, 'mousedown').map(event => ({ x: event.clientX, y: event.clientY })); const up = Rx.Observable.fromEvent(document, 'mouseup'); // 记录mousemove时的坐标 const move = Rx.Observable.fromEvent(document, 'mousemove').map(event => ({ x: event.clientX, y: event.clientY })); const drag = down.switchMap(downPos => move.pipe( // 只保留和初始坐标有差异的移动事件 filter(movePos => movePos.x !== downPos.x || movePos.y !== downPos.y), takeUntil(up), take(1) // 如果只需要捕获第一次有效拖拽动作就保留,要持续拖拽就删掉这行 ) );
额外说明
不同浏览器对mousemove的触发时机有细微差异,Firefox等浏览器不会在mousedown后立即触发无位移的mousemove,所以这个过滤逻辑主要是为了兼容Chrome这类有特殊行为的浏览器。如果你的需求是持续监听拖拽过程,直接去掉take(1)就可以了,过滤逻辑依然能帮你避免初始的无效触发。
内容的提问来源于stack exchange,提问作者bjorkblom
相关产品推荐
相关产品推荐

