如何使用react拖放内容?

时间:2018-01-23 13:22:45

标签: javascript html reactjs drag-and-drop

我需要从这个div中渲染内容:

  <div class="col-sm-4">
                  <ul class="list-group">
                  <li class="list-group-item"><a href="#">File Reader</a></li>
                  <li class="list-group-item" ><a href="#">File Move</a></li>
                  <li class="list-group-item" ><a href="#">Data Base</a></li>
                  <li class="list-group-item"><a href="#">SAP R3</a></li>
                  <li class="list-group-item"><a href="#">FTP</a></li>
                  <li class="list-group-item"><a href="#">SOAP</a></li>
                  <li class="list-group-item"><a href="#">Rest</a></li>
                  <li class="list-group-item"><a href="#">Merge</a></li>
                  <li class="list-group-item"><a href="#">Filter</a></li>
                  <li class="list-group-item"><a href="#">Transform</a></li>
              </ul>
              </div>

进入拖放,我尝试了很多例子,但似乎没有任何效果。

这是我现在的代码:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { ItemTypes } from './Constants';
import styles2 from './Styles.css'
import { render } from 'react-dom';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center', 
};



function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  };
}
function _(id){
   return document.getElementById(id);  
}
var droppedIn = false;
function drag_start(event) {
    _('app_status').innerHTML = "Dragging the "+event.target.getAttribute('id');
    event.dataTransfer.dropEffect = "move";
    event.dataTransfer.setData("text", event.target.getAttribute('id') );
}
function drag_enter(event) {
    _('app_status').innerHTML = "You are dragging over the "+event.target.getAttribute('id');
}
function drag_leave(event) {
    _('app_status').innerHTML = "You left the "+event.target.getAttribute('id');
}
function drag_drop(event) {
    event.preventDefault(); /* Prevent undesirable default behavior while dropping */
    var elem_id = event.dataTransfer.getData("text");
    event.target.appendChild( _(elem_id) );
    _('app_status').innerHTML = "Dropped "+elem_id+" into the "+event.target.getAttribute('id');
    _(elem_id).removeAttribute("draggable");
    _(elem_id).style.cursor = "default";
    droppedIn = true;
}
function drag_end(event) {
    if(droppedIn == false){
        _('app_status').innerHTML = "You let the "+event.target.getAttribute('id')+" go.";
    }
  droppedIn = false;
}
function readDropZone(){
    for(var i=0; i < _("drop_zone").children.length; i++){
        alert(_("drop_zone").children[i].id+" is in the drop zone");
    }
    /* Run Ajax request to pass any data to your server */
}
const propTypes = {
  text: PropTypes.string.isRequired,

  // Injected by React DnD:
  isDragging: PropTypes.bool.isRequired,
  connectDragSource: PropTypes.func.isRequired
};

class BasicForm extends React.Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }



   render() {
    return (

      <div style={styles}>
       <form onSubmit={this.handleSubmit}>


        <div class="container">
            <div class="row">
             <div class="col-sm-4">
                      <ul class="list-group">
                      <li class="list-group-item"><a href="#">File Reader</a></li>
                      <li class="list-group-item" ><a href="#">File Move</a></li>
                      <li class="list-group-item" ><a href="#">Data Base</a></li>
                      <li class="list-group-item"><a href="#">SAP R3</a></li>
                      <li class="list-group-item"><a href="#">FTP</a></li>
                      <li class="list-group-item"><a href="#">SOAP</a></li>
                      <li class="list-group-item"><a href="#">Rest</a></li>
                      <li class="list-group-item"><a href="#">Merge</a></li>
                      <li class="list-group-item"><a href="#">Filter</a></li>
                      <li class="list-group-item"><a href="#">Transform</a></li>
                  </ul>
                  </div>
              <h2 id="app_status">App status...</h2>
              <h1>Drop Zone</h1>
              <div id="drop_zone"  onDragEnter="drag_enter(event)" onDrop="drag_drop(event)" onDragOver="return false" onDragLeave="drag_leave(event)" className={styles2.drop_zone} ></div>

              </div>
          </div>
          <input type="submit" value="Submit" />
      </form>  
       </div>
    );
  }

}export default DragDropContext(HTML5Backend)(BasicForm);

在我的控制台上我收到此错误:预期onDragEnter侦听器是一个函数,而是获得string类型的值。 我做错了什么? PS:我是React的新手,我尝试了很多例子,所以代码有点大。

2 个答案:

答案 0 :(得分:2)

这是react中列表的基本拖放示例。尚不能处理拖放操作,只能处理拖动和滚动操作。

const getWindowScroll = () => {
    const doc = document.documentElement;
    return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
  }

class App extends React.Component {
  setElemRef = ref => {
    this.elemRef = ref;
  }
  
  initialiseDrag = event => {
    const {target, clientY} = event;
    const { offsetTop } = target;
    const { top } = this.elemRef.getBoundingClientRect();
    this.dragStartTop = top - offsetTop;
    this.dragStartY = clientY;
    window.addEventListener('mousemove', this.startDragging, false);
    window.addEventListener('mouseup', this.stopDragging, false);
  }
  
  startDragging = ({ clientY }) => { 
    let newTop = this.dragStartTop + clientY - this.dragStartY + getWindowScroll();
    if (newTop < 0) newTop = 0;
    this.elemRef.style.transform = `translateY(${newTop}px)`;
    this.scrollIfElementBottom(newTop);
  }

  stopDragging = () => {
    window.removeEventListener('mousemove', this.startDragging, false);
    window.removeEventListener('mouseup', this.stopDragging, false);
  }  
  
  scrollIfElementBottom = newTop => {
    if (newTop > 30) {
      window.scroll({
        top: newTop,
        behavior: 'smooth'
      });    
    }
    if (newTop < 30) {
      window.scroll({
        top: 0,
        behavior: 'smooth'
      });      
    }
  };
  
  render(){
    return (
      <React.Fragment>
        <div onMouseDown={this.initialiseDrag} ref={this.setElemRef}>DragMe</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
      </React.Fragment>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
#root div {
  background: gray;
  padding: 20px;
  margin: 10px;
  user-select: none;
  cursor: pointer;
  border: 1px solid lightgray;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

https://github.com/peterh32/react-drag-drop-container是一个非常简单的库。如果我了解您要执行的操作(将LI拖放到“拖放区域”中),则可以对每个LI进行以下操作:

<DragDropContainer onDrop={...} onDragStart={...} ...etc. >
  <li class="list-group-item"><a href="#">File Reader</a></li>
</DragDropContainer>

...然后是您的放置区域:

<DropTarget onHit={...} onDragEnter={...} ...etc.>
  <div id="drop-target">...</div>
</DropTarget>

您可以看到事件直接进入了容器。它可以处理鼠标和触摸界面,还可以进行诸如滚动到屏幕边缘时的滚动之类的操作(因此您可以拖动到最初不在屏幕上的目标位置)。