在 ReactJS 中实现基本的拖动功能

IT技术 javascript reactjs
2021-05-07 14:49:40

基于 create-react-app 模板,我正在尝试实现一个非常基本的拖/放场景。App.js目前看起来像这样:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    const myStyle = {
      height: '100px',
      width: '200px',
      top: '50px',
      left: '100px',
      position: 'absolute',
      borderStyle: 'solid',
      borderColor: 'blue',      
    };

    return (

      <div className="App">        
          <div style={myStyle} draggable>test</div>
          <div>test2</div>        
      </div>
    );
  }
}

export default App;

我的问题是,从我看过的所有教程和文档中,我理解添加draggable属性会导致元素可拖动,但事实并非如此。

需要设置哪些附加属性才能创建对象draggable(我对在这个阶段放弃任何东西都不感兴趣。)

3个回答

这可以是 React 中拖动行为的核心实现。它当然需要增强功能,而且还不能处理删除:

const { useRef } = React

const App = () => {
  const elemRef = useRef(null)
  const dragProps = useRef()
  
  const initialiseDrag = event => {
    const { target, clientX, clientY } = event
    const { offsetTop, offsetLeft } = target
    const { left, top } = elemRef.current.getBoundingClientRect()
    
    dragProps.current = {
      dragStartLeft: left - offsetLeft,
      dragStartTop: top - offsetTop,
      dragStartX: clientX,
      dragStartY: clientY
    }
    window.addEventListener('mousemove', startDragging, false)
    window.addEventListener('mouseup', stopDragging, false)
  }
  
  
  const startDragging = ({ clientX, clientY }) => {    
    elemRef.current.style.transform = `translate(${dragProps.current.dragStartLeft + clientX - dragProps.current.dragStartX}px, ${dragProps.current.dragStartTop + clientY - dragProps.current.dragStartY}px)`
  } 

  const stopDragging = () => {
    window.removeEventListener('mousemove', startDragging, false)
    window.removeEventListener('mouseup', stopDragging, false)
  }
  
  return (
    <div
      onMouseDown={initialiseDrag}
      ref={elemRef}
      >
      DragMe
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'));
div {
  cursor: grab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

由于我无法运行您当前的 ReactJS 应用程序,我拼凑了一个简短的示例来展示拖放功能的不同实例。

正如您在示例中看到的,为draggable元素设置属性应该使元素可拖动,就像在典型网页上拖动图像一样。

您能否确认在拖动元素时,它根本不移动,如不可拖动的代码片段所示

var draggable = document.getElementById('draggable');

function onDragStart(event) {
    event.dataTransfer.setData('text/html', null); //cannot be empty string
    var counter = document.getElementById('counter');
    counter.innerText = parseInt(counter.innerText, 10) + 1;
}

draggable.addEventListener('dragstart', onDragStart, false);
#draggable{
    width: 100px;
    height: 100px;
    background: blue;
    margin: 10px 5px;
}

#notdraggable{
    width: 100px;
    height: 100px;
    background: red;
    margin: 10px 5px;
}

#draggableNDT{
      width: 100px;
    height: 100px;
    background: green;
    margin: 10px 5px;
} 
   <div>Draggable (<span id='counter'>0</span>)</div>
    <div id='draggable' draggable='true'></div>
    
    <div><pre>Draggable (No DataTransfer)</div>
    <div id='draggableNDT' draggable></div>
    
    <div><pre>Not Draggable</div>
    <div id='notdraggable' draggable='false'></div>

您可以查看react-draggable库,只需将组件包装在 Draggable 组件中

安装 npm i react-draggable

进口 import Draggable from 'react-draggable'

用法:

<Draggable 
   axis="both"
   cancel="input, textarea, span, label"
>
  <div style={myStyle}>test</div>
</Draggable>