自定义表格_可拖拽排序

在做后台管理系统的时候,经常需要表格里面的每行排序,自定义可拖拽表格,更改样式方便。

一、实现效果

 进行拖拽演示:

可拖拽排序表格

无滚动条样式:

有滚动条样式:

二、代码

使用react+scss+ts,实现页面。

在pages文件夹下新建一个文件夹 tablePage 。然后在tablePage 下面新建两个文件,index.tsx   ,    index.scss  。

index.tsx 

import './index.scss';
import { useState, useEffect } from "react";

function FileTest() {

  // 表格body的滚动条
  const [scrollWidth, setScrollWidth] = useState(0)

  //挂载后,计算表格body是否有滚动条,从而改变宽度(页面高度变化,以及表格展示内容条数变化,都需要调用此方法)
  function changeWidth() {
    var myElement: any = document.getElementById('myElement');
    var widthWithBorder = myElement.offsetWidth;
    var widthWithoutBorder = myElement.clientWidth;
    setScrollWidth(widthWithBorder - widthWithoutBorder);
  }

  useEffect(() => {
    changeWidth();
  }, []);

  //表格标题,和宽度占父元素百分比,(采用百分比的方式,是因为需要进行电脑大小屏适配,这样可以确保表格充满屏幕),字符串为空的地方是间隔。
  let tableTitle = [
    ['', 2],
    ['序号', 5],
    ['姓名', 12],
    ['', 1],
    ['部门', 12],
    ['', 1],
    ['组织', 30],
    ['', 1],
    ['时间', 10],
    ['', 1],
    ['状态', 10],
    ['', 1],
    ['操作', 14]
  ]

  //-------------------------------------------------  拖拽   ----------------------------------------------------------------/

  const [dragging, setDragging] = useState(null)

  function dragStart(e: any) {
    e.stopPropagation();
    setDragging(e.target); // 保存被拖动的行
  }

  // 判断是兄还是弟
  function getSort(draggingElement: any, targetElement: any, tbody: any) {
    var siblings = [];
    let number = tbody.children.length
    for (var i = 0; i < number; i++) {
      siblings.push(tbody.children[i]);
    }
    // 正在拖拽的
    var index = siblings.indexOf(draggingElement);
    // 当前悬浮的
    var targetIndex = siblings.indexOf(targetElement);

    if (targetIndex > -1) {
      if (index === targetIndex) {
        return false;
      } else {
        if (targetIndex === number.length - 1) {
          // 此时在最后插入元素
          return null;
        } else if (index < targetIndex) {
          return siblings[targetIndex + 1] || null;
        } else if (index > targetIndex) {
          return siblings[targetIndex] || null;
        }
      }
    }
    return null;
  }

  function onDropEvent(e: any) {
    e.preventDefault();
    e.stopPropagation();
    var table: any = document.getElementById('sortable-table');
    var tbody = table.getElementsByTagName('tbody')[0];

    if (dragging) {
      var afterElement = getSort(dragging, e.target, tbody);
      if (e.target && e.target.tagName === "TR") {
        e.target.style.border = '';
        e.target.style.borderBottom = '1px solid #F2F5F4';

        if (afterElement !== false) {
          if (afterElement === null) {
            tbody.appendChild(dragging);
          } else {
            tbody.insertBefore(dragging, afterElement);
          }
        }

      }
    }
  }

  function onDragOverEvent(e: any) {
    e.preventDefault(); // 阻止默认行为
    if (e.target.tagName === "TR") {
      e.target.style.border = '1px solid #1BCEB2';
    }
  }

  function ondragLeave(e: any) {
    // 清除拖拽区域样式
    if (e.target.tagName === "TR") {
      e.target.style.border = '';
      e.target.style.borderBottom = '1px solid #F2F5F4';
    }
  }

  return (
    <div className='omm-edu-Manage-box-set'>
      {/* 左侧和上侧,留有导航栏位置 ,如不需要,直接将top和left设置为0即可*/}
      <div className="omm-edu-Manage-content-set">

        {/* 表格 */}
        <div className="omm-table-father-set">
          <table border={0} className='omm-table-box-set' id="sortable-table">

            <thead>
              <tr className='omm-table-title-box-set'>
                {tableTitle.map((item, index) => (
                  <th key={index} className='omm-table-title-set' style={{ width: `${item[1]}%` }}>
                    {item[0]}</th>
                ))}
              </tr>
            </thead>

            <tbody className='omm-table-content-box-all-set' id="myElement" style={{ width: `calc(100% + ${scrollWidth}px)` }} onDrop={(e) => { onDropEvent(e) }} onDragOver={(e) => { onDragOverEvent(e) }} onDragLeave={(e) => { ondragLeave(e) }}>
              {[1, 2, 3, 4, 5, 6, 7].map((item, indexA) => (
                <tr key={indexA} className='omm-table-content-box-set' draggable="true" onDragStart={(e) => { dragStart(e) }}>
                  {tableTitle.map((item, index) => (
                    <td key={index} className='omm-table-content-set' style={{ width: `${item[1]}%` }}>

                      {index === 1 ? indexA
                        : item[0]
                      }

                    </td>
                  ))}
                </tr>
              ))}
            </tbody>

          </table>
        </div>
      </div>

    </div>
  );
}

export default FileTest;

index.scss

table {
    border-collapse: collapse;
}

.omm-edu-Manage-box-set {
    width: 100%;
    height: 100%;
    background-color: #F7FAF8;

    .omm-edu-Manage-content-set {
        position: absolute;
        top: 72px;
        left: 216px;
        right: 20px;
        bottom: 12px;
        background-color: #fff;
        border-radius: 12px;
        min-width: 1000px;
        min-height: 500px;
        padding: 16px;

        .omm-table-father-set {
            position: absolute;
            top: 16px;
            left: 16px;
            right: 16px;
            bottom: 79px;

            .omm-table-box-set {
                width: 100%;

                .omm-table-title-box-set {
                    height: 42px !important;
                    max-height: 42px !important;
                    background: #F2F5F4;
                    width: 100%;
                    position: relative;
                    z-index: 1;

                    .omm-table-title-set {
                        height: 42px !important;
                        max-height: 42px !important;
                        color: #505553;
                        font-size: 14px;
                        font-weight: normal;
                        text-align: left;
                    }
                }

                .omm-table-content-box-all-set {
                    overflow-y: auto;
                    position: absolute;
                    top: 42px;
                    left: 0;
                    right: 0;
                    bottom: 0;

                    .omm-table-content-box-set {
                        min-height: 44px !important;
                        border-bottom: 1px solid #F2F5F4;
                        position: relative;
                        width: 100%;
                        word-wrap: break-word;
                        font-size: 14px;
                        padding: 5px 0;
                        box-sizing: border-box;
                        display: flex;
                        align-items: center;

                        &:hover {
                            background: #F7FAF8;
                            cursor: pointer;
                        }

                        .omm-table-content-set {
                            display: inline-block;
                            vertical-align: middle;
                            height: 100%;
                            color: #1E201F;
                            font-size: 14px;
                            font-weight: normal;
                            pointer-events: none;
                        }
                    }
                }
            }
        }
    }
}

现在在当前页面使用,后期会提取为公共组件,使用更方便,也让拖拽样式有更多选择。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值