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

推荐阅读