react 拖拽排序

Posted 羊哥很嗨

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react 拖拽排序相关的知识,希望对你有一定的参考价值。

  react 拖拽排序。项目中用到了,记一笔。没有用react-dnd, 没有用react-beautiful-dnd, 因为需求简单,所以就自己撸了一个。

  代码很简单

  定义css, 两个动画
  

.drag-up {
  -webkit-animation: dragup ease 0.2s 1;
          animation: dragup ease 0.2s 1;
  -webkit-animation-fill-mode: forwards;
          animation-fill-mode: forwards;
  background-color: red;
}
.drag-down {
  -webkit-animation: dragdown ease 0.2s 1;
          animation: dragdown ease 0.2s 1;
  -webkit-animation-fill-mode: forwards;
          animation-fill-mode: forwards;
  background-color: green;
}
@-webkit-keyframes dragup {
  from {
    margin-top: 10px;
  }
  to {
    margin-top: 60px;
  }
}
@keyframes dragup {
  from {
    margin-top: 10px;
  }
  to {
    margin-top: 60px;
  }
}
@-webkit-keyframes dragdown {
  from {
    margin-bottom: 10px;
    margin-top: 60px;
  }
  to {
    margin-bottom: 60px;
    margin-top: 10px;
  }
}
@keyframes dragdown {
  from {
    margin-bottom: 10px;
    margin-top: 60px;
  }
  to {
    margin-bottom: 60px;
    margin-top: 10px;
  }
}

  一个是向上拖拽的动画,一个是向下拖拽的样式。

 

2.写组件

class List extends React.Component {
  constructor(props) {
    super(props);
    this.state = {...props};
  }

  dragStart(e) {
    this.dragged = e.currentTarget;
  }
  dragEnd(e) {
    this.dragged.style.display = ‘block‘;

    e.target.classList.remove("drag-up");
    this.over.classList.remove("drag-up");

    e.target.classList.remove("drag-down");
    this.over.classList.remove("drag-down");
    

    var data = this.state.data;
    var from = Number(this.dragged.dataset.id);
    var to = Number(this.over.dataset.id);
    data.splice(to, 0, data.splice(from, 1)[0]);

    //set newIndex to judge direction of drag and drop
    data = data.map((doc, index)=> {
      doc.newIndex = index + 1;
      return doc;
    })

    this.setState({data: data});
  }

  dragOver(e) {
    e.preventDefault();

    this.dragged.style.display = "none";
    
    if (e.target.tagName !== "LI") {
      return;
    }

    //判断当前拖拽target 和 经过的target 的 newIndex

    const dgIndex = JSON.parse(this.dragged.dataset.item).newIndex;
    const taIndex = JSON.parse(e.target.dataset.item).newIndex;
    const animateName = dgIndex > taIndex ? "drag-up" : "drag-down";


    if (this.over && e.target.dataset.item !== this.over.dataset.item) {
      this.over.classList.remove("drag-up", "drag-down");
    }

    if(!e.target.classList.contains(animateName)) {
      e.target.classList.add(animateName);
      this.over = e.target;
    }
  }
  render() {
    var listItems = this.state.data.map((item, i) => {
      return (
        <li 
          data-id={i}
          key={i}
          style={{height: "60px", border: "solid 1px #cccccc", margin: "10px 30%", borderRadius: "5px", backgroundColor: "green", color: "#ffffff"}}
          draggable=‘true‘
          onDragEnd={this.dragEnd.bind(this)}
          onDragStart={this.dragStart.bind(this)}
          data-item={JSON.stringify(item)}
        >{item.color}</li>
      )
     });
    return (
      <ul onDragOver={this.dragOver.bind(this)} className ="contain">
        {listItems}
      </ul>
    )
  }
}
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: [
        {
          newIndex: 1,
          color: "red"
        },

        {
          newIndex: 2,
          color: "green"
        },

        {
          newIndex: 3,
          color: "blue"
        },

        {
          newIndex: 4,
          color: "yellow"
        },

        {
          newIndex: 5,
          color: "orange"
        },

        {
          newIndex: 6,
          color: "black"
        }
      ]
    }
  }
  render() {
    return (
      <div>
        <List data={this.state.data} /> 
      </div>
    )
  }
}



ReactDOM.render(
  <App />,
  document.getElementById(‘app‘),
);

 

解释几个三个方法
1.dragStart  把 target 赋值给了this

2.dragOver 把经过的 li 赋值给了 this, 并且在经过的li上,添加对应的class, 实现动画效果。 这里比较了序号,判断当前是向哪个方向拖拽。  并且比较了 经过li是否是同一个,不是的话,移除动画效果。

3.dragEnd, 移除动画效果, 并且比较数据,setState到最新的数据。

 

总结, 有点dom操作的思想。

demo地址: https://codepen.io/jhonyoung/pen/PeGpNL

原创。

 

以上是关于react 拖拽排序的主要内容,如果未能解决你的问题,请参考以下文章

基于H5实现的react拖拽排序组件

react 自定义拖拽排序列表

拖拽排序插件 ---- Dragula

react 表格单元格拖拽

简单拖拽即生成网页 VvvebJs

element+sortablejs插件实现拖拽排序效果