自定义表格_可拖拽排序

news2025/1/13 10:34:36

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

一、实现效果

 进行拖拽演示:

可拖拽排序表格

无滚动条样式:

有滚动条样式:

二、代码

使用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;
                        }
                    }
                }
            }
        }
    }
}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1959329.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring-原理篇-RequestMappingHandlerMapping 全流程是怎样的呢?

首先来看Controller 中的每个处理器是怎么样被扫描的 我们可以看到在这个AutoConfigurationSupport中&#xff0c;注册了这个RequestMappingHandlerMapping 这个Bean。 RequestMappingHandlerMapping实现了InitializingBean 这个接口&#xff0c;其逻辑在父类AbstractHandler…

CISAW信息安全保障人员认证是否值得学习?

CISAW信息安全保障人员认证的学习难度因人而异。 如果考生具备足够的学习能力以及丰富的信息安全工作经验&#xff0c;那么考试的难度可能会相对较低。 相反&#xff0c;如果考生缺少这些条件&#xff0c;学习难度可能会相对较高。 1. 从考试内容来看&#xff0c;CISAW以概念…

提升朋友圈曝光率:自动转发,让你告别复制粘贴

想要提高朋友圈的曝光率&#xff0c;单靠手动发布和复制粘贴已远远不够。 今天&#xff0c;我将告诉你如何利用工具&#xff0c;来实现自动转发&#xff0c;让你的朋友圈推广效率更高&#xff0c;轻松提升互动率。 首先&#xff0c;在个微管理系统上登录所有的微信号&#xf…

vue2使用wangeditor5及word导入解析的实现与问题

安装 wangeditor5 官网&#xff1a;https://www.wangeditor.com/v5/ yarn add wangeditor/editor # 或者 npm install wangeditor/editor --saveyarn add wangeditor/editor-for-vue # 或者 npm install wangeditor/editor-for-vue --save mammoth.js 官网&#xff1a;https…

vue2 vue3 props 的处理机制

在 Vue 2 中&#xff0c;props 是单向数据流&#xff0c;父组件向子组件传递的 props 默认情况下是不具有响应式特性的。这意味着当父组件的数据发生变化时&#xff0c;如果传递给子组件的 props 发生变化&#xff0c;子组件不会自动更新视图。 具体来说&#xff0c;在 Vue 2 …

Linux安装青龙面板并将本地服务映射至公网实现远程访问

文章目录 前言一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 …

【Java】韩顺平Java学习笔记 第19章 IO流

文章目录 文件概述常用的文件操作创建文件获取文件信息目录的操作和文件删除流的分类各抽象类常用子类对象FileInputStreamFileOutputStreamFileReaderFileWriter 节点流和处理流概念BufferedReaderBufferedWriterBufferedInputStream & BufferedOutputStream 对象流&#…

代发考生战报:7月22号,广州,HCIP-Cloud Service SA云服务 H13-821考试通过

代发考生战报&#xff1a;7月22号&#xff0c;广州&#xff0c;HCIP-Cloud Service SA云服务 H13-821考试通过&#xff0c;遇到7-10个新题&#xff0c;剩下都是题库里的原题&#xff0c;记住了考试要带两个证件才行&#xff0c;我用的是身份证和驾照&#xff0c;想考的抓紧考吧…

php实现动态登录

简介&#xff1a; 效果&#xff1a;通过前端页面的注册&#xff0c;通过MD5将密码加密&#xff0c;发送到数据库&#xff0c;通过验证数据库的内容实现登录&#xff0c;以及各种保证安全的措施 实验环境&#xff1a;phphtmlcssmysql数据表&#xff0c;使用html css设计注册&a…

do语句——输入两个值求和

代码如下&#xff1a; #include<stdio.h> int main() {int sum0;int a,b;puts("请输入两个整数");printf("整数a:"); scanf("%d",&a);printf("整数b:"); scanf("%d",&b);int t(a>b)?b:a;do{sumsumt;tt1;…

PHP基于微信小程序的打车平台-计算机毕业设计源码78689

摘 要 本文介绍的是基于PHP开发的打车平台小程序。该系统旨在为用户提供一个便捷、高效的平台&#xff0c;以实现网约车的打车功能。随着社交媒体和互联网的普及&#xff0c;网约车已成为日常交通中常见的形式。然而&#xff0c;传统的打车方式存在不方便、不及时等问题。 微信…

【Kafka】对 kafka 消费程序客户端进行监控采集

前言 对于 Kafka 组件而言&#xff0c;我们通常会对 kafka 服务端添加一些监控&#xff0c;来确保服务的稳定性&#xff0c;虽然有 kafka-exporter 来对消费者进行监控&#xff0c;但是指标很少&#xff0c;对于生产者和消费者更细粒度的监控就无法做到了。只能将监控部署在客…

DDPM 核心代码解析(1)

所有代码 已上传至GitHub - duhanyue349/diffusion_model_learned_ddpm_main: 扩散模型基础框架源代码 目录结构如下 在train_cifar.py 中展示了扩散模型训练的所有代码 如果没有安装wandb 可以在create_argparser()设置 log_to_wandbFalse 一、加载模型参数 args 这里用了一…

语音转文字在线免费有什么工具?这4款工具让记录更高效

在当今职场、学术界和内容创作领域&#xff0c;人们越来越需要一种高效的方式来整理会议记录、讲座内容或采访对话。 幸运的是&#xff0c;除了传统的手动记笔记方式&#xff0c;我们还可以通过录音转文字软件来实现这一目标。这些软件能够直接将音频资料转写为文本&#xff0…

4nm点状激光模组的应用让未来科技走向潮流

在科技发展时代&#xff0c;激光技术以其高精度、高效率的特性&#xff0c;正逐步成为众多行业不可或缺的核心技术之一。其中&#xff0c;4nm点状激光模组作为激光技术领域的佼佼者&#xff0c;凭借其卓越的性能和广泛的应用前景&#xff0c;正引领着科技发展的新潮流。接下来我…

ubuntu20.04.6 安装Skywalking 10.0.1

1.前置准备 1.1. **jdk17&#xff08;Skywalking10 jdk22不兼容&#xff0c;用17版本即可&#xff09;**安装&#xff1a; https://blog.csdn.net/CsethCRM/article/details/140768670 1.2. elasticsearch安装&#xff1a; https://blog.csdn.net/CsethCRM/article/details…

Apollo:源码分析之cyber/mainboard启动入口介绍-my write, test ok

软件结构图 cyber入口 cyber的入口在"cyber/mainboard"目录中: ├── mainboard.cc // 主函数 ├── module_argument.cc // 模块输入参数 ├── module_argument.h ├── module_controller.cc // 模块加载,卸载 └── module_controller.…

Feature Corrective Transfer Learning (2024CVPR)

Feature Corrective Transfer learning Framework &#xff08;特征矫正迁移学习框架&#xff09; 旨在引导非理想图像上的模型训练与理想图像上训练的模型的特中层更紧密地对齐 Model Selection and Training on Ideal Images 首先在理想图像上训练&#xff0c;得到理想参数…

NV170D语音芯片:为洗地扫地一体机带来新体验!

随着物联网、人工智能技术的飞速发展&#xff0c;家用电器的智能化转型已成为不可逆转的趋势。在这一背景下&#xff0c;洗地扫地一体机&#xff0c;作为家务自动化的先锋&#xff0c;融合了高效清洁与便捷操作的双重优势&#xff0c;而语音芯片的应用&#xff0c;更是为其增添…

使用 nvm在linux上安装多个版本的node

使用 nvm&#xff08;Node Version Manager&#xff09;: nvm 是一个流行的 Node.js 版本管理工具&#xff0c;允许你安装和使用多个版本的 Node.js。 1、安装nvm wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash source ~/.nvm/nvm.sh2、…