el-table每隔数行生成一个小计,最终生成一个合计
- element本身功能已经很齐全了,但实际开发中肯定会伴随着各种奇葩要求,譬如根据日期统计几行的【小计】,然后最终再根据所有小计数据统计出【合计】。
- show me the code!
- 首先,el-table提供的自定义合计方法返回的是一个数组,其数组项就是对应列的数据,譬如第0列一般是序号,第5列是需要统计的那么 sums[4] = 42 就会在最终渲染时让该列的【合计】行上显示42。因此无论是根据表格当前分页数据计算而来,还是后端返回的统计数据,都可以在只需要合计行的情况下轻松设置。
- Table 表格 | Element Plus (element-plus.org) 参照官网的默认合计demo
- 若是需要小计,个人想到的方法是修改表格数据,在需要的地方插入一条新数据,以此实现需求
- 注:该方法是更改data本身,因此数据长度必定发生变化,以及默认的序号列(type="index")会标记小计与合计行。若是有分页需求的,请考虑在修改完数据后修改分页器的size(最大显示条目数)确保所有数据能够渲染;若是有序号标记需求的,请手动设置序号列(prop=“index”)并在正确的数据上设置该值。
-
//计算小计 const processData = computed(()=>{ let subtotal = 0 //小计数量 let temp = [] //重新渲染的数组 let division = 0 //以日期作为合计分割点 testData.value.forEach((item, index)=>{ //给原数据添加序号 item.index = index + 1 temp.push(item) //同一个日期内 if(item.findate === testData.value[index + 1]?.findate){ //同一个站 if(item.locationname === testData.value[index + 1]?.locationname){ //同一种票 if(item.tickettypename === testData.value[index + 1]?.tickettypename){ subtotal += item.ticketnum } else {//不同票据 subtotal += item.ticketnum temp.push({index: null, tickettypename: '小计', ticketnum: subtotal}) subtotal = 0 } } else{//不同站点 subtotal += item.ticketnum temp.push({index: null, tickettypename: '小计', ticketnum: subtotal}) subtotal = 0 } } else {//不同日期,添加一个小计与合计 subtotal += item.ticketnum temp.push({index: null, tickettypename: '小计', ticketnum: subtotal}) subtotal = 0 temp.push({index: '', tickettypename: '总计', ticketnum: testData.value.slice(division, index + 1).reduce((total, item) => total + item.ticketnum, 0)}) division = index + 1 //新的分割点 } }) state.pagination.total = temp.length state.pagination.size = temp.length return temp }) //渲染小计和总计的样式 const rowStyle = ({row}) => { if(row.tickettypename === '小计') return ('background: #EFEFEF; color: red') else if(row.tickettypename === '总计') return ('background: #FCCFDB; font-weight: 700') }
实际效果如下
-
计算逻辑可以自己写。我这里使用了分页,渲染完毕后把分页器的size设置为了新数据的长度,total不变(毕竟你切页的时候是请求新数据了,譬如21~40的原始数据,前一页渲染了多少行不影响);
- 同时序号是自定义的列;
知识点:
1、object?.property:【?.】是语法糖,能够避免访问undefined的属性而报错,譬如
obj = {age: 18}, obj.name.length //error!
obj.name?.length //undefined
2、array.reduce(function(total, currentValue, currentIndex, arr), initialValue):这是个遍历数组的方法(用作累加器),第一个参数为回调函数,第二个参数为累加初始值。
total为传入下次回调的值,若是设置初始值则为初始值,否则为数组第一项;
currentValue为数组当前元素;
currentIndex为数组当前元素索引;
arr为当前元素所属数组(直接用array也可以)
//譬如有数组如下
let arr = [4,10,22,10]
arr.reduce((toal, item)=>total + item) //output: 46
3、一开始要让我适应组合式API写法是拒绝的,因为下意识的认为这是绑定TS语法,类型判断实在是太过吹毛求疵了(对于目前的项目而言),而且选项式API风格很标准,依赖、组件、变量、方法、生命周期钩子一目了然,该放哪儿就在哪儿。但之后发现这样写出来的在后期维护修bug的时候很折磨(尤其是我的idea现在导向声明时灵时不灵)。于是我转向了组合式风格,不得不说实在是太爽了。引入依赖、变量声明、方法全都可以扎堆写成一坨,维护的时候一找就能全部找到了,写起来也很爽(可能这就是屎山初体验吧哈哈哈,因为我看element的示例demo里,他们还是很标准地将类型声明、依赖引入、变量、方法各自分在一块儿,没有聚在一起)