拖拽排序

react项目拖拽排序,本想搞一搞 dnd插件等生态,奈何项目太老 版本太低,参考网上的手写 做了一个组件。

import React from 'react';
import {Icon} from 'antd';
import styles from './index.less';

export default class List extends React.Component {
  dragStart(e) {
    this.dragged = e.currentTarget;
  }
  dragEnd(e) {
    this.dragged.style.display = 'flex';

    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.props.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.props.sorted(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.props.data.map((item, i) => {
      return (
        <li
          data-id={i}
          key={i}
          className={styles.list}
          draggable="true"
          onDragEnd={this.dragEnd.bind(this)}
          onDragStart={this.dragStart.bind(this)}
          data-item={JSON.stringify({...item, newIndex: i})}
        >
          {item.name}
          {!this.props.disabled ? (
            <Icon
              type="close"
              onClick={() => this.props.onCloseTag(item.id)}
            ></Icon>
          ) : null}
        </li>
      );
    });
    return (
      <ul onDragOver={this.dragOver.bind(this)} style={{padding: 0}}>
        {listItems}
      </ul>
    );
  }
}
.list{
    user-select: none;
    padding: 0px 10px;
    border-radius: 4px;
    display: flex;
    justify-content: space-between;
    border: 1px solid #d8d8d8;
    align-items: center;
    margin-bottom: 5px;
}

需要注意的地方

  • 因为是排序,所以传进来的值需要在排序后更新。
  • 选择后进行拖拽排序,这样要保证选中的值是按当前的顺序进行排序
posted @ 2021-01-05 17:52  橙云生  阅读(323)  评论(0编辑  收藏  举报