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
0
投稿
猜你喜欢
- 在日常Java后端开发过程中,免不了对数据字段的解析,自然就少不了对字符串的操作,这其中就包含了正则表达式这一块的内容,这里面涉及Java包
- 最近在D4得到一本(美) Penny Mcintire写的《Visual Design for the Modern Web》.突然觉得可用
- PyType_Type和PyBaseObject_TypePyObject和PyTypeObject内容的最后指出下图中对实例对象和类型对象
- 费茨法则是人机交互领域里一个非常重要的法则,在10年来得到了广泛的应用。Fitts法则最基本的观点就是任何时候,当一个人用鼠标来移动鼠标指针
- 本文实例讲解了php表单验证的实现方法,分享给大家供大家参考,具体内容如下1.PHP表单处理welcome.html<html>
- 本程序有两文件test.asp 和tree.asp 还有一些图标文件 1。test.asp 调用类生成树 代码如下<%@
- FSO中除了可以对驱动器、文件夹的操作以外,功能最强大的就是对文件的操作了。它可以用来记数、内容管理、搜索还可生成动态HTML页面等等。一、
- 今天碰到这个极度郁闷的报错,搞了大半下午,才发现是ie的问题,忍不住大骂。例子是这样的:页面中有多处能出发菜单,并且菜单出现在触发点的旁边,
- 在一些项目中, 我们会使用json 来将字符串转为结构体,但是很多时候,这种结构体只会用一次,基本上只会用于反序列化, 对于这种只用到一次的
- 今天小池提出一个问题讨论,如何使分页做的更友好。做了一些调研和思考,做了些总结。分页在电商网站3级页、搜索结果页面等信息量大的页面是很重要的
- 下面是模板的一般形式,显示了指定 SQL 查询和 XPath 查询的方式: <ROOT xmlns:sql="ur
- 每次在操作数据库的时候最烦的就是根据表单提交的内容写sql语句,特别是字段比较多的时候很麻烦,动不动就容易写错。所以我就写了下面的生成sql
- 背景:pony是公司的首席体验官、首席产品经理。这次在产品峰会上pony将自己平时经验的积累与大家交流,体验较细。这次分享研发管理部,设计中
- 本文主要介绍了一个获取SQL Server数据字典的经典SQL语句,大家可以根据各自的实际情况对这段语句进行相应的修改。SELECT sys
- 一、什么是 Postman(前世今生)Postman 诞生于 2013 年,一开始只是 Abhinav Asthana 着手于解决 API
- 简介ORA-10458: standby database requires recoveryORA-01196: 文件 1 由于介质恢复会
- 你还没用 jQuery 写过导航菜单? 相信看到这些出色的jQuery导航菜单后,一定会为此而后悔没早点把 jQuery 应用到自己的Web
- 在cssplay网站看到有一组CSS像素画,于是也想摩仿一下,于是在网络上找到一组头像图标,看其结构比较简单,就拿它开刀吧!先看看预览图图一
- 这里列出了javascript 中的document.execCommand() 的各种参数说明:2D-Position 允许通过
- 阅读上一篇:FrontPage XP设计教程1——站点初建与管理接下来的工作就是读者朋友们最为关心的网页的制作和编辑了。我们知道,一个站点是