我正在参加「掘金·启航计划」
概述
如题,今天在处理 “拖拽” 时,遇到的一个小问题
<Draggable>
<button onClick={handleClick}>我是一个可拖拽的按钮</button>
</Draggable>
上述代码,在使用 react-draggable 库(目前用的是 "react-draggable": "^4.4.5" 的版本 )实现拖拽时,一旦拖拽结束,就会误触被 <Draggable> 包裹的元素中的 click 事件
解决方案
通过手动维护一个“是否处于拖拽状态”的标识来做判断,详情可见:线上 Demo (PS:这个好像需要科学上网)
演示
如上图,在拖拽的时候虽然也触发了包裹的元素中的 click 事件,但因为我们手动维护一个 isDragging 的标识(“是否处于拖拽状态”),这样我们就可以按需执行我们的 click 逻辑
代码
import * as React from 'react';
import Draggable from 'react-draggable';
import './style.css';
export default function App() {
let isDragging = false;
const handleDrag = () => {
isDragging = true;
};
const handleStop = () => {
console.log('handleStop');
// 触发 onStop 后会触发 onClick,加个 setTimeout 是为了让修改不“马上”发生,导致 handleClick 拿到的不是预期的结果
setTimeout(() => (isDragging = false), 0);
};
const handleClick = () => {
console.log('handleClick');
if (isDragging) {
return;
}
console.log('啊,我被 click 了');
};
return (
<div>
<p>react-draggable 拖拽时规避误触发内容中的 click 事件</p>
<Draggable onDrag={handleDrag} onStop={handleStop}>
<button onClick={handleClick}>我是一个可拖拽的按钮</button>
</Draggable>
</div>
);
}
还是贴一下代码吧,避免有些朋友科学上网不便 ( ̄3 ̄)a
对了,顺便想给 码上掘金 提个小建议,个人感觉现在 码上掘金 的功能还是不够全面,基本只能写传统 JS 代码,想引入第三方库或者使用React、Vue 时一运行就报错~
个人体验了比较多个线上代码平台,感觉 stackblitz 会相对好用一点,但要科学上网,而且也不能像 码上掘金 直接嵌套进掘金的文章当中。有好几次都想用 码上掘金 写,但最终都是被其相对不是很好用的情况劝退了 ( ̄. ̄)
言归正传,上述代码中比较关键的是 setTimeout(() => (isDragging = false), 0); 这一步,我们简单说明一下:
handleDrag、handleStop、handleClick,这三个函数会依次执行- 在
handleDrag中设置isDragging = true; - 如果在
handleStop直接设置isDragging = false;的话,等到handleClick执行时,isDragging的值将会是false,这样并不符合我们的预期 - 所以要通过
setTimeout(() => (isDragging = false), 0);将其变成一个异步调用,这样,在handleClick执行时,isDragging的值还是true,符合我们的预期- 对这块不是很熟的朋友,可以深入了解一下:JavaScript的工作原理:事件循环及异步编程,这种做法还是挺常见的