本文实例为大家分享了React实现表格选取的具体代码,供大家参考,具体内容如下
在工作中,遇到一个需求,在表格中实现类似于Excel选中一片区域的,然后拿到选中区域的所有数据。
1.实现需求和效果截图1.获取选中区域的数据
2.选择的方向是任意的
3.支持几行 / 几列的选取
4.通过生产JSON给后台进行交互
5.标记出表头和第一行的数据
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