猿问

使用钩子在 React 中拖放

我主要是一名后端工程师,一直在尝试为我在 React 中制作的滑块实现简单的拖放操作,但失败了。


首先,我将向您展示不使用 debounce 的行为: no-debounce


这是 debounce 的行为: with-debounce


我从这里得到的 debounce 做了一点修改。


我想我有两个问题,一个是快速闪烁,应该去抖动解决,另一个是不正确的left,我不知道如何解决。出于某种原因,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>


谢谢你。


尚方宝剑之说
浏览 160回答 1
1回答

拉风的咖菲猫

Draggable 和 onDrag 有其自身的问题。用简单的鼠标事件尝试了我的手。它的来源如下import React, { useRef, useState, useEffect, useCallback } from "react";import ReactDOM from "react-dom";import "./styles.css";function App() {&nbsp; const isDragging = useRef(false);&nbsp; const dragHeadRef = useRef();&nbsp; const [position, setPosition] = useState(0);&nbsp; const onMouseDown = useCallback(e => {&nbsp; &nbsp; if (dragHeadRef.current && dragHeadRef.current.contains(e.target)) {&nbsp; &nbsp; &nbsp; isDragging.current = true;&nbsp; &nbsp; }&nbsp; }, []);&nbsp; const onMouseUp = useCallback(() => {&nbsp; &nbsp; if (isDragging.current) {&nbsp; &nbsp; &nbsp; isDragging.current = false;&nbsp; &nbsp; }&nbsp; }, []);&nbsp; const onMouseMove = useCallback(e => {&nbsp; &nbsp; if (isDragging.current) {&nbsp; &nbsp; &nbsp; setPosition(position => position + e.movementX);&nbsp; &nbsp; }&nbsp; }, []);&nbsp; useEffect(() => {&nbsp; &nbsp; document.addEventListener("mouseup", onMouseUp);&nbsp; &nbsp; document.addEventListener("mousedown", onMouseDown);&nbsp; &nbsp; document.addEventListener("mousemove", onMouseMove);&nbsp; &nbsp; return () => {&nbsp; &nbsp; &nbsp; document.removeEventListener("mouseup", onMouseUp);&nbsp; &nbsp; &nbsp; document.removeEventListener("mousedown", onMouseDown);&nbsp; &nbsp; &nbsp; document.removeEventListener("mousemove", onMouseMove);&nbsp; &nbsp; };&nbsp; }, [onMouseMove, onMouseDown, onMouseUp]);&nbsp; return (&nbsp; &nbsp; <div&nbsp; &nbsp; &nbsp; style={{&nbsp; &nbsp; &nbsp; &nbsp; flex: "1",&nbsp; &nbsp; &nbsp; &nbsp; display: "flex",&nbsp; &nbsp; &nbsp; &nbsp; alignItems: "center",&nbsp; &nbsp; &nbsp; &nbsp; justifyContent: "center",&nbsp; &nbsp; &nbsp; &nbsp; height: "100vh"&nbsp; &nbsp; &nbsp; }}&nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; <div&nbsp; &nbsp; &nbsp; &nbsp; style={{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: "5px",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width: "500px",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; background: "black",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; position: "absolute"&nbsp; &nbsp; &nbsp; &nbsp; }}&nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; <div&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref={dragHeadRef}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style={{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left: `${position}px`,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; transition: 'left 0.1s ease-out',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; top: "-12.5px",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; position: "relative",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: "30px",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width: "30px",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; background: "black",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; borderRadius: "50%"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }}&nbsp; &nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; );}const rootElement = document.getElementById("root");ReactDOM.render(<App />, rootElement);逻辑的关键是e.movementX返回自上次发生该事件以来鼠标沿 x 轴移动的距离量。使用它来设置dragHeader的左侧位置
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答