为了账号安全,请及时绑定邮箱和手机立即绑定

使用钩子在 React 中拖放

使用钩子在 React 中拖放

尚方宝剑之说 2022-01-13 20:00:37
我主要是一名后端工程师,一直在尝试为我在 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>谢谢你。
查看完整描述

1 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

Draggable 和 onDrag 有其自身的问题。用简单的鼠标事件尝试了我的手。

它的来源如下


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);

逻辑的关键是e.movementX返回自上次发生该事件以来鼠标沿 x 轴移动的距离量。使用它来设置dragHeader的左侧位置


查看完整回答
反对 回复 2022-01-13
  • 1 回答
  • 0 关注
  • 159 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信