在做后台管理系统的时候,经常需要表格里面的每行排序,自定义可拖拽表格,更改样式方便。
一、实现效果
进行拖拽演示:
可拖拽排序表格
无滚动条样式:
有滚动条样式:
二、代码
使用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.lengthfor (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;}}}}}}
}
现在在当前页面使用,后期会提取为公共组件,使用更方便,也让拖拽样式有更多选择。