1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > antd Table 组件动态合并单元格

antd Table 组件动态合并单元格

时间:2022-09-03 01:46:20

相关推荐

antd Table 组件动态合并单元格

antd Table 组件动态合并单元格

前言Table 组件静态数据合并单元格Table 组件动态数据合并单元格总结

前言

使用 antd 开发 PC端应用的人肯定知道的 Table 组件。一个功能很完善,界面很优化的表格组件。通过查阅官方文档,你可以很轻松地使用这个组件。但是如果表格中涉及到合并单元格昵?

文档中也有关于合并单元格的处理,但是只是静态数据的范例。而我们开发中往往都是获取的动态数据。那么Table 组件改如何动态合并单元格昵?

Table 组件静态数据合并单元格

这里简单地讲一下核心步骤,详细的步骤请直接移步官方文档。

以上是个简单的表格。现在我们将【分类】中相同的值合并,达到如下效果。

实现思路:

找到要合并列的第一列所在位置。记为 index。并且设置 rowSpan 为合并总列数。

这里需要将 index 为 0 的 rowSpan 设置为 2。后面的相同项(也就是 index 为 1) 的 rowSpan 设置为 0。同样地,需要将 index 为 2 的 rowSpan 设置为 1(没有相同项,就设置为1。也可以不用设置 rowSpan)。最后,将 index 为 3 的 rowSpan 设置为 3,后面的相同项(也就是 index 为 4/5) 的 rowSpan 设置为 0。

const columns = [{title: '分类',dataIndex: 'category',render: (value, row, index) => {const obj = {children: value,props: {},};if (index === 0) {obj.props.rowSpan = 2;}if (index === 1) {obj.props.rowSpan = 0;}//没有相同项时可以不用设置 colSpan if (index === 2) {obj.props.rowSpan = 1;}if (index === 3) {obj.props.rowSpan = 3;}if (index === 4) {obj.props.rowSpan = 0;}if (index === 5) {obj.props.rowSpan = 0;}return obj;} },{title: '名称',dataIndex: 'name',},{title: '评价',dataIndex: 'desc',},];const data = [{"category":"水果","name": "桃子", "desc": "好吃"},{"category":"水果","name": "梨子", "desc": "真好吃"},{"category":"蔬菜","name": "茄子", "desc": "真TM好吃"},{"category":"家禽","name": "牛肉", "desc": "太好吃了"},{"category":"家禽","name": "羊肉", "desc": "好吃到停不下来"},{"category":"家禽","name": "猪肉", "desc": "吃不起,太贵"}]

实现静态数据单元格合并总结一下就是两点。

设置合并列的第一列 rowSpan 为合并数。设置其他相同项 rowSpan 为 0。

以上是处理静态数据,我们能够很快找到合并列的第一列以及合并数。但是如果是动态数据昵?我们不知道有几个【水果】,几个【蔬菜】和几个【肉类】。

Table 组件动态数据合并单元格

我最开始的想法是在 columns 对象的 render 中去完成这个功能。因为 render 中本来就是循环,暴露的参数又有限,所以很难去对比每个对象的相同项。后来经大牛指导可以先处理数据源。render 中直接使用带有逻辑的数据源就好了。

于是茅塞顿开,涉及到要处理数据逻辑,那么这个问题就转换成了一道算法题。

算法题:

假如在真实的开发场景中接口返回如下数据格式。

let data = [{"category":"水果","name": "桃子", "desc": "好吃"},{"category":"水果","name": "梨子", "desc": "真好吃"},{"category":"蔬菜","name": "茄子", "desc": "真TM好吃"},{"category":"家禽","name": "牛肉", "desc": "太好吃了"},{"category":"家禽","name": "羊肉", "desc": "好吃到停不下来"},{"category":"家禽","name": "猪肉", "desc": "吃不起,太贵"}]

界面要求:将【分类】中相同值进行合并单元格。

经过上面对静态数据的逻辑处理,我们知道需要将每个相同项的第一项的 rowSpan 设置为合并数。并且其他的相同项设置为 0。得到后的数据格式如下:

data = [{"category":"水果","name": "桃子", "desc": "好吃","rowSpan":2 },{"category":"水果","name": "梨子", "desc": "真好吃","rowSpan":0 },{"category":"蔬菜","name": "茄子", "desc": "真TM好吃","rowSpan":1},{"category":"家禽","name": "牛肉", "desc": "太好吃了","rowSpan":3},{"category":"家禽","name": "羊肉", "desc": "真不错", "rowSpan":0},{"category":"家禽","name": "猪肉", "desc": "吃不起,太贵", "rowSpan":0}]

算法题解思路:

定义 count 为重复项的第一项索引。定义 indexCount 为下一项的索引。取出数组第一个对象 item,先将 rowSpan 初始化为1。然后将 item 的【分类】值与下一项进行对比,发现一个相同项,rowSpan 就加1,并且下一项的 rowSpan 设置为 0。每对比一次,indexCount 累加。当没有遇到相同项时将 indexCount 赋值给 count。获取下一个相同项首项。按照1/2/3的步骤,数组循环完之后就可以正确的赋值 rowSpan。

代码:

import dataJson from './data/Table.json';let data = dataJson.data;let field = 'category';const changeData = (data,field)=>{let count = 0;//重复项的第一项let indexCount = 1;//下一项while (indexCount<data.length){var item = data.slice(count,count+1)[0];//获取没有比较的第一个对象if(!item.rowSpan){item.rowSpan = 1;//初始化为1}if(item[field] === data[indexCount][field]){//第一个对象与后面的对象相比,有相同项就累加,并且后面相同项设置为0item.rowSpan++;data[indexCount].rowSpan = 0;}else {count = indexCount;}indexCount++;}}changeData(data,field);//处理数据

总结

总结就一句话:数据处理逻辑思维,MVC 和 MVP 思想

最开始做这个功能的时候,我一直沉浸在渲染页面 column 对象的 render 函数里去处理逻辑。但是 render 里面本来就是一个循环,参数有限,所以思维变得非常拘泥。

经大神点播可以先把数据源处理好再直接渲染页面,我才发应过来这种业务逻辑最好的处理方式就是直接处理数据状态,用数据状态代替业务逻辑。这不就是所谓的 MVC 和 MVP 思想吗?所以程序设计思维真的很重要。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。