Javascript 使用挂钩拖放React
我主要是一个后端工程师,一直在尝试实现,但失败了,一个简单的拖放滑块我在反应 首先,我将向您展示不使用debounce的行为: 以下是debounce的行为: 我稍微修改了一下,从中取出的去盎司 我想我有两个问题,一个是快速闪烁,去抖动应该解决,另一个是不正确的Javascript 使用挂钩拖放React,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我主要是一个后端工程师,一直在尝试实现,但失败了,一个简单的拖放滑块我在反应 首先,我将向您展示不使用debounce的行为: 以下是debounce的行为: 我稍微修改了一下,从中取出的去盎司 我想我有两个问题,一个是快速闪烁,去抖动应该解决,另一个是不正确的左,我不知道如何修复。出于某种原因,onDrag,rect.left也将父对象(100+10)的所有左边距添加到它。这发生在Chrome和Safari上 我的问题是,我如何使这个拖放工作?我做错了什么?我的代码如下: import
左,我不知道如何修复。出于某种原因,onDrag,rect.left也将父对象(100+10)的所有左边距添加到它。这发生在Chrome和Safari上
我的问题是,我如何使这个拖放工作?我做错了什么?我的代码如下:
import React, {
Dispatch,
MouseEvent,
RefObject,
SetStateAction,
useEffect,
useRef,
useState
} from "react";
const useDebounce = (callback: any, delay: number) => {
const latestCallback = useRef(callback);
const latestTimeout = useRef(1);
useEffect(() => {
latestCallback.current = callback;
}, [callback]);
return (obj: any) => {
const { event, args } = obj;
event.persist();
if (latestTimeout.current) {
clearTimeout(latestTimeout.current);
}
latestTimeout.current = window.setTimeout(
() => latestCallback.current(event, ...args),
delay
);
};
};
const setPosition = (
event: any,
setter: any
) => {
const rect = event.target.getBoundingClientRect();
const clientX: number = event.pageX;
console.log('clientX: ', clientX)
// console.log(rect.left)
setter(clientX - rect.left)
};
const Slider: React.FC = () => {
const [x, setX] = useState(null);
const handleOnDrag = useDebounce(setPosition, 100)
return (
<div style={{ position: "absolute", margin: '10px' }}>
<div
style={{ position: "absolute", left: "0", top: "0" }}
onDragOver={e => e.preventDefault()}
>
<svg width="300" height="10">
<rect
y="5"
width="300"
height="2"
rx="10"
ry="10"
style={{ fill: "rgb(96,125,139)" }}
/>
</svg>
</div>
<div
draggable={true}
onDrag={event => handleOnDrag({event, args: [setX]})}
// onDrag={event => setPosition(event, setX)}
style={{
position: "absolute",
left: (x || 0).toString() + "px",
top: "5px",
width: "10px",
height: "10px",
padding: "0px",
}}
>
<svg width="10" height="10" style={{display:"block"}}>
<circle cx="5" cy="5" r="4" />
</svg>
</div>
</div>
);
};
import-React{
派遣,
MouseEvent,
重新设定目标,
采取行动,
使用效果,
useRef,
使用状态
}从“反应”;
const useDebounce=(回调:any,延迟:number)=>{
const latestCallback=useRef(回调);
const latestTimeout=useRef(1);
useffect(()=>{
latestCallback.current=回调;
},[callback]);
返回(对象:任何)=>{
const{event,args}=obj;
event.persist();
if(最晚超时。当前){
clearTimeout(latestTimeout.current);
}
latestTimeout.current=window.setTimeout(
()=>latestCallback.current(事件,…参数),
延迟
);
};
};
常数设置位置=(
事件:任何,
塞特:有吗
) => {
const rect=event.target.getBoundingClientRect();
const clientX:number=event.pageX;
log('clientX:',clientX)
//console.log(rect.left)
setter(clientX-rect.left)
};
常量滑块:React.FC=()=>{
const[x,setX]=useState(null);
常数handleOnDrag=useDebounce(设置位置,100)
返回(
e、 preventDefault()}
>
handleOnDrag({event,args:[setX]})}
//onDrag={event=>setPosition(event,setX)}
风格={{
位置:“绝对”,
左:(x | | 0).toString()+“px”,
顶部:“5px”,
宽度:“10px”,
高度:“10px”,
填充:“0px”,
}}
>
);
};
谢谢。拖拉和翁德拉也有自己的不幸。用简单的鼠标事件尝试我的手
您可以在下面的沙箱中找到一个工作代码
其来源如下
import React, { useRef, useState, useEffect, useCallback } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
const isDragging = useRef(false);
const dragHeadRef = useRef();
const [position, setPosition] = useState(0);
const onMouseDown = useCallback(e => {
if (dragHeadRef.current && dragHeadRef.current.contains(e.target)) {
isDragging.current = true;
}
}, []);
const onMouseUp = useCallback(() => {
if (isDragging.current) {
isDragging.current = false;
}
}, []);
const onMouseMove = useCallback(e => {
if (isDragging.current) {
setPosition(position => position + e.movementX);
}
}, []);
useEffect(() => {
document.addEventListener("mouseup", onMouseUp);
document.addEventListener("mousedown", onMouseDown);
document.addEventListener("mousemove", onMouseMove);
return () => {
document.removeEventListener("mouseup", onMouseUp);
document.removeEventListener("mousedown", onMouseDown);
document.removeEventListener("mousemove", onMouseMove);
};
}, [onMouseMove, onMouseDown, onMouseUp]);
return (
<div
style={{
flex: "1",
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100vh"
}}
>
<div
style={{
height: "5px",
width: "500px",
background: "black",
position: "absolute"
}}
>
<div
ref={dragHeadRef}
style={{
left: `${position}px`,
transition: 'left 0.1s ease-out',
top: "-12.5px",
position: "relative",
height: "30px",
width: "30px",
background: "black",
borderRadius: "50%"
}}
/>
</div>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React,{useRef,useState,useffect,useCallback}来自“React”;
从“react dom”导入react dom;
导入“/styles.css”;
函数App(){
const isDragging=useRef(false);
const dragHeadRef=useRef();
const[position,setPosition]=useState(0);
const onMouseDown=useCallback(e=>{
if(dragHeadRef.current&&dragHeadRef.current.contains(e.target)){
IsDraging.current=真;
}
}, []);
const onMouseUp=useCallback(()=>{
if(IsDraging.current){
IsDraging.current=假;
}
}, []);
const onMouseMove=useCallback(e=>{
if(IsDraging.current){
设置位置(位置=>position+e.movementX);
}
}, []);
useffect(()=>{
文件。添加了监听器(“mouseup”,onMouseUp);
文件。添加了文本列表(“鼠标向下”,onMouseDown);
document.addEventListener(“mousemove”,onMouseMove);
return()=>{
文件。删除EventListener(“mouseup”,onMouseUp);
文档。删除EventListener(“mousedown”,onMouseDown);
document.removeEventListener(“mousemove”,onMouseMove);
};
},[onMouseMove,onMouseDown,onmousedup]);
返回(
);
}
const rootElement=document.getElementById(“根”);
render(,rootElement);
逻辑的关键是e.movementX
,它返回自上次事件发生以来鼠标沿x轴移动的距离量。用它来设置dragHeader的左侧位置通过使用范围
类型的输入
,您可以简化您的生活。单击此处查看示例滑块:(包括一个工作代码沙盒示例)@MattCarlotta这可能会让我的生活更轻松。谢谢。非常感谢@johnny peter,不过我想知道,如果输入列表为空,为什么要使用useCallback,即依赖项为空,并且每次都会运行,换句话说,为什么不使用普通函数?这只是一个小的性能优化。如果它是一个普通函数,那么在每次渲染时都会创建一个新函数,这将触发不必要地调用useEffect。