React实现表格选取
作者:追逐蓦然 发布时间:2023-08-25 02:56:17
标签:React,表格选取
本文实例为大家分享了React实现表格选取的具体代码,供大家参考,具体内容如下
在工作中,遇到一个需求,在表格中实现类似于Excel选中一片区域的,然后拿到选中区域的所有数据。
1.实现需求和效果截图
1.获取选中区域的数据
2.选择的方向是任意的
3.支持几行 / 几列的选取
4.通过生产JSON给后台进行交互
5.标记出表头和第一行的数据
2.核心代码解析
2.1区域选择
onClick={() => {
// 区间选取
if (itemIndex != 0) {
setType('slide')
/**
第一个点击的时候,打开鼠标移动的逻辑
区间选取的时候,要标记第一次选中点的(x,y)坐标。
同时初始化x,y的最小最大值。
**/
if(isStart == 0){
setIsStart(1)
setStartItemIndex(itemIndex)
setStartDataIndex(dataIndex)
setMaxItemIndexs(itemIndex)
setMaxDataIndexs(dataIndex)
setMinItemIndexs(itemIndex)
setMinDataIndexs(dataIndex)
}else {
//第二次点击的时候,关闭鼠标移动的逻辑
setIsStart(0)
}
}
// 行选取
if (itemIndex == 0) {
setType('row')
setIsStart(1)
setColumnIndexList([])
if (rowIndexList.indexOf(dataIndex) != -1) {
let obj = [...rowIndexList]
obj.deleteElementByValue(dataIndex)
setRowIndexList(obj)
} else {
let obj = [...rowIndexList]
obj.push(dataIndex)
setRowIndexList(obj)
}
}
}}
2.2鼠标移动效果
onMouseOver={() => {
if (isStart) {
if(itemIndex!= 0 ){
//比较当前值跟第一次点击值的大小,随时调整最大值和最小值。从而达到选中区域的效果
if (itemIndex > startItemIndex) {
setMinItemIndexs(startItemIndex)
setMaxItemIndexs(itemIndex)
} else {
setMaxItemIndexs(startItemIndex)
setMinItemIndexs(itemIndex)
}
}
if (dataIndex > startDataIndex) {
setMinDataIndexs(startDataIndex)
setMaxDataIndexs(dataIndex)
}
else {
setMaxDataIndexs(startDataIndex)
setMinDataIndexs(dataIndex)
}
}
}}
2.3生产JSON数据逻辑
<Button type="primary" onClick={() => {
if (type == 'slide') {
// 区域选择
// 数据体
let obj = {}
// 表头集合
let headerList = []
// 第一列集合
let firstRow = []
for (let i = minDataIndexs; i <= maxDataIndexs; i++) {
obj[data['数据集'][i]] = []
if(firstRow.indexOf(data['数据集'][i]) == -1){
firstRow.push(data['数据集'][i])
}
for (let j = minItemIndexs; j <= maxItemIndexs; j++) {
let dataObj = {}
dataObj[header[j].name] = data[header[j].name][i]
if(headerList.indexOf(header[j].name) == -1){
headerList.push(header[j].name)
}
obj[data['数据集'][i]].push(dataObj)
}
}
console.log(firstRow);
console.log(headerList);
console.log(obj);
} else if (type == 'row') {
// 几行选中
let obj = {}
let headerList = []
let firstRow = []
rowIndexList.map(item => {
obj[data['数据集'][item]] = []
firstRow.push(data['数据集'][item])
header.map((headerItem, headerIndex) => {
if (headerIndex != 0) {
let dataObj = {}
if(headerList.indexOf(headerItem.name) == -1){
headerList.push(headerItem.name)
}
dataObj[headerItem.name] = data[headerItem.name][item]
obj[data['数据集'][item]].push(dataObj)
}
})
})
console.log(firstRow);
console.log(headerList);
console.log(obj);
} else if (type == 'column') {
// 几列选中
let headerList = []
let firstRow = []
let obj = {}
data['数据集'].map((item, index) => {
obj[item] = []
firstRow.push(item)
columnIndexList.map(i => {
let dataObj = {}
if(headerList.indexOf(header[i].name) == -1){
headerList.push(header[i].name)
}
dataObj[header[i].name] = data[header[i].name][index]
obj[item].push(dataObj)
})
})
console.log(firstRow);
console.log(headerList);
console.log(obj);
}
}}>确定</Button>
3.完成代码
import { Button } from 'antd';
import React, { useState } from 'react';
function Index(params) {
// 删除数组中第一个匹配的元素,成功则返回位置索引,失败则返回 -1。
Array.prototype.deleteElementByValue = function (varElement) {
var numDeleteIndex = -1;
for (var i = 0; i < this.length; i++) {
// 严格比较,即类型与数值必须同时相等。
if (this[i] === varElement) {
this.splice(i, 1);
numDeleteIndex = i;
break;
}
}
return numDeleteIndex;
}
// 表头
const [header, setHeader] = useState([
{
name: "数据集",
},
{
name: '19春支付金额',
},
{
name: '20春支付金额',
},
{
name: '21春支付金额',
},
{
name: '19春支付人数',
},
{
name: '20春支付人数',
},
{
name: '21春支付人数',
}
])
// 数据
const [data, setData] = useState({
'数据集': ['连衣裙', '裤子', '衬衫', '短袖', '长袖', '短裤', '羽绒服', '棉毛裤'],
'19春支付金额': [10000, 5000, 10000, 5000, 10000, 5000, 10000, 5000],
'20春支付金额': [12000, 5200, 12000, 5200, 12000, 5200, 12000, 5200],
'21春支付金额': [14000, 5400, 14000, 5400, 14000, 5400, 14000, 5400],
'19春支付人数': [1000, 500, 1000, 500, 1000, 500, 1000, 500],
'20春支付人数': [1200, 520, 1200, 520, 1200, 520, 1200, 520],
'21春支付人数': [1400, 540, 1400, 540, 1400, 540, 1400, 540],
})
//
const [isStart, setIsStart] = useState(0)
// 类型
const [type, setType] = useState('')
// // 起始
const [startItemIndex, setStartItemIndex] = useState(-1)
const [startDataIndex, setStartDataIndex] = useState(-1)
// 小
const [minItemIndexs, setMinItemIndexs] = useState(-1)
const [minDataIndexs, setMinDataIndexs] = useState(-1)
// 大
const [maxItemIndexs, setMaxItemIndexs] = useState(-1)
const [maxDataIndexs, setMaxDataIndexs] = useState(-1)
// 行下标
const [rowIndexList, setRowIndexList] = useState([])
// 列下标
const [columnIndexList, setColumnIndexList] = useState([])
return (
<div>
<div style={{ marginLeft: 200 }}>
<div style={{ display: 'flex' }}>
<Button type="primary" onClick={() => {
if (type == 'slide') {
// 区域选择
let obj = {}
let headerList = []
let firstRow = []
for (let i = minDataIndexs; i <= maxDataIndexs; i++) {
obj[data['数据集'][i]] = []
if(firstRow.indexOf(data['数据集'][i]) == -1){
firstRow.push(data['数据集'][i])
}
for (let j = minItemIndexs; j <= maxItemIndexs; j++) {
let dataObj = {}
dataObj[header[j].name] = data[header[j].name][i]
if(headerList.indexOf(header[j].name) == -1){
headerList.push(header[j].name)
}
obj[data['数据集'][i]].push(dataObj)
}
}
console.log(firstRow);
console.log(headerList);
console.log(obj);
} else if (type == 'row') {
// 几行选中
let obj = {}
let headerList = []
let firstRow = []
rowIndexList.map(item => {
obj[data['数据集'][item]] = []
firstRow.push(data['数据集'][item])
header.map((headerItem, headerIndex) => {
if (headerIndex != 0) {
let dataObj = {}
if(headerList.indexOf(headerItem.name) == -1){
headerList.push(headerItem.name)
}
dataObj[headerItem.name] = data[headerItem.name][item]
obj[data['数据集'][item]].push(dataObj)
}
})
})
console.log(firstRow);
console.log(headerList);
console.log(obj);
} else if (type == 'column') {
// 几列选中
let headerList = []
let firstRow = []
let obj = {}
data['数据集'].map((item, index) => {
obj[item] = []
firstRow.push(item)
columnIndexList.map(i => {
let dataObj = {}
if(headerList.indexOf(header[i].name) == -1){
headerList.push(header[i].name)
}
dataObj[header[i].name] = data[header[i].name][index]
obj[item].push(dataObj)
})
})
console.log(firstRow);
console.log(headerList);
console.log(obj);
}
}}>确定</Button>
{/* <Button type="primary" danger onClick={()=>{
setStartItemIndex(-1)
setRowIndexList([])
setColumnIndexList([])
setType('')
}}>重置</Button> */}
</div>
<div style={{ display: 'flex', textAlign: "center" }}>
{
header.map((item, index) => {
return <div style={{ minWidth: 100, border: "1px solid #ccc" }} onClick={() => {
setType('column')
setRowIndexList([])
if (columnIndexList.indexOf(index) != -1) {
let obj = [...columnIndexList]
obj.deleteElementByValue(index)
setColumnIndexList(obj)
} else {
let obj = [...columnIndexList]
obj.push(index)
setColumnIndexList(obj)
}
}}>{item.name}</div>
})
}
</div>
<div style={{ display: 'flex', textAlign: "center" }}>
{
header.map((item, itemIndex) => {
return <div>
{
data[item.name].map((data, dataIndex) => {
return <div onClick={() => {
// 区间选取
if (itemIndex != 0) {
setType('slide')
if(isStart == 0){
setIsStart(1)
setStartItemIndex(itemIndex)
setStartDataIndex(dataIndex)
setMaxItemIndexs(itemIndex)
setMaxDataIndexs(dataIndex)
setMinItemIndexs(itemIndex)
setMinDataIndexs(dataIndex)
}else {
setIsStart(0)
}
}
// 行选取
if (itemIndex == 0) {
setType('row')
setIsStart(1)
setColumnIndexList([])
if (rowIndexList.indexOf(dataIndex) != -1) {
let obj = [...rowIndexList]
obj.deleteElementByValue(dataIndex)
setRowIndexList(obj)
} else {
let obj = [...rowIndexList]
obj.push(dataIndex)
setRowIndexList(obj)
}
}
}} onMouseOver={() => {
if (isStart) {
if(itemIndex!= 0 ){
if (itemIndex > startItemIndex) {
setMinItemIndexs(startItemIndex)
setMaxItemIndexs(itemIndex)
} else {
setMaxItemIndexs(startItemIndex)
setMinItemIndexs(itemIndex)
}
}
if (dataIndex > startDataIndex) {
setMinDataIndexs(startDataIndex)
setMaxDataIndexs(dataIndex)
}
else {
setMaxDataIndexs(startDataIndex)
setMinDataIndexs(dataIndex)
}
}
}} style={{
minWidth: 100, border: "1px solid #ccc",
backgroundColor: type == 'slide' ?
(itemIndex >= minItemIndexs && itemIndex <= maxItemIndexs) && (dataIndex >= minDataIndexs && dataIndex <= maxDataIndexs) ? 'pink' : '' :
type == 'row' ? rowIndexList.indexOf(dataIndex) != -1 ? 'pink' : '' :
type == 'column' ? columnIndexList.indexOf(itemIndex) != -1 ? 'pink' : '' : ''
}}>{data}</div>
})
}
</div>
})
}
</div>
</div>
</div>
)
}
export default Index
来源:https://blog.csdn.net/qq_35905501/article/details/120952542


猜你喜欢
- Django 中的时区在现实环境中,存在有多个时区。用户之间很有可能存在于不同的时区,并且许多国家都拥有自己的一套夏令时系统。所以如果网站面
- 就前面所讲,函数的基本内容已经完毕。但是,函数还有很多值得不断玩味的细节。这里进行阐述。参数的传递python中函数的参数通过赋值的方式来传
- 引言本篇是以python的视角介绍相关的函数还有自我使用中的一些问题,本想在这篇之前总结一下opencv编译的全过程,但遇到了太多坑,暂时不
- 前言在github中经常可以看到下面的日历图,可以用来表示每一天在github上的活跃程度。类似的方法也可以用到空气质量的可视化方式中来,只
- 最近对H1的讨论很多(在文章内容页中),大致有以下两种情况:H1应该用于文章的标题上H1应该用于站点的标题上相信大多数人都偏向第一种方式:用
- 摘要:本文介绍了字符与编码的发展过程,相关概念的正确理解。举例说明了一些实际应用中,编码的实现方法。然后,本文讲述了通常对字符与编码的几种误
- 如下所示:# coding:utf-8import shapefilew = shapefile.Writer()w.autoBalance
- 本文实例讲述了Python爬虫实现的根据分类爬取豆瓣电影信息功能。分享给大家供大家参考,具体如下:代码的入口:if __name__ ==
- 一、准备工作安装最新的Go1、由于Google被墙的原因,如果没有VPN的话,就到这里下载:http://www.golangtc.com/
- 这篇文章主要介绍了python yield和Generator函数用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参
- Apache 从2.2升级到 Apache2.4.x 后配置文件 httpd.conf 的设置方法有了大变化,以前是将 deny from
- 准备1、下载所需安装包wget https://www.php.net/distributions/php-7.4.0.tar.gzwget
- 背景今天在工作中,同事遇到一个上传图片的问题:系统要求的图片大小不能超过512KB。但是同事又有很多照片。这要是每一个照片都用ps压缩的话,
- MicroPython是Python 3语言的精简高效实现,包括Python标准库的一小部分,经过优化可在微控制器和受限环境中运行。WiFi
- 为什么能实现在线编辑呢? 首先需要ie 的支持,在 ie 5.5以后就有一个编辑状态,就是利用这个编辑状态,然后用javascript 来控
- 什么是进程进程就是操作系统中执行的一个程序,操作系统以进程为单位分配存储空间,每个进程都有自己的地址空间、数据栈以及其他用于跟踪进程执行的辅
- 1.元组的创建元组(tuple):元组本身是不可变数据类型,没有增删改查元组内可以存储任意数据类型t = (1,2.3,True,'
- //测试函数 function test(str){ alert(str); } // 方法一 window["test"
- 本文实例讲述了Go语言结构体定义和使用方法。分享给大家供大家参考。具体分析如下:一个结构体(struct)就是一个字段的集合。(而 type
- 对于相册来说,大图的浏览非常重要,因为对浏览者来说最重要的就是大图看得爽不爽,因为做项目的需要,我比较了许多相册的大图浏览方式,现在一一评说