ElementUI el-table笔记

一、el-table滚动条移到合计的下方

当我们将elementUI的参数show-summary设置为true时,有时候滚动条会出现在合计行的上方,如何移动到合计行下方:

1、直接添加css样式,复制即用

::v-deep .el-table--scrollable-x .el-table__body-wrapper{
	overflow-x: hidden!important;
	z-index: 2!important;}
	
::v-deep .el-table__footer-wrapper {
	overflow-x: auto;
	border-top: 1px solid #f4f4f4;}

2、监听footerWrapper滚动条

① table添加ref="detailTable" (detailTable只是随便取的一个名字而已,这里如果要修改,记得下面mounted里面也有同步修改)

 <el-table
                        border
                        :data="processedData"
                        style="width: 100%"
						:header-cell-style="{background:'#f5f7fa'}"
						:span-method="spanRows"
						show-summary
						ref="detailTable"
					
                    >

② mounted监听,复制即用

mounted() {
	    var tableBody = this.$refs.detailTable.$refs.footerWrapper
	    tableBody.addEventListener('scroll', () => {
	      // 滚动距离
	      const scrollLeft = tableBody.scrollLeft
	      this.$refs.detailTable.$refs.bodyWrapper.scrollLeft = scrollLeft
	    })

	  },
为什么是 detailTable
  • ref 是你自己定义的标识符名称,可以随意命名。在你的代码里,你为 <el-table> 组件指定了 ref="detailTable",这使得你可以在 this.$refs.detailTable 中访问该组件。
  • 通过 this.$refs.detailTable,你就可以访问该表格组件内部的一些子组件引用,比如 footerWrapper(合计行)和 bodyWrapper(数据主体部分的滚动条)。
滚动同步代码的原理
  1. this.$refs.detailTable.$refs.footerWrapper 是表格的合计行区域。
  2. addEventListener('scroll', ...) 监听合计行的滚动事件,每当用户在合计行滚动时触发回调。
  3. this.$refs.detailTable.$refs.bodyWrapper.scrollLeft = scrollLeft 通过设置表格数据主体部分(bodyWrapper)的 scrollLeft 值,使得它跟随合计行滚动条的滚动距离保持一致。

二、自定义合计行(只在最下面显示合计)

因为 show-summary 计算的合计,会将已合并的数值✖行数(例如,735*4+340*4...),如果仅需要累加一次合并了单元格的数值,需要自定义合计方法 

1、定义summary-method方法

<el-table
                        border
                        :data="processedData"
                        style="width: 100%"
						:header-cell-style="{background:'#f5f7fa'}"
						:span-method="spanRows"
						:summary-method="getSummary"
					
                    >

2、使用set集合避免重复累加

//计算合计
		getSummary() {
		    const summary = {
		        crklrcssum: 0,  //初始化“领入纯水”
		        crkckslsum: 0,  //初始化“出库数量”
		    };
		
		    const uniqueValues = new Set();  //uniqueValues 被定义为一个 Set 集合,用于跟踪并存储 crklrcssum 字段中已经累计的值,避免重复累加。
		
		    this.processedData.forEach(item => {
		        if (item.crklrcssum && !uniqueValues.has(item.crklrcssum)) {
		            summary.crklrcssum += Number(item.crklrcssum);
		            uniqueValues.add(item.crklrcssum);
		        }
		        if (item.crkckslsum) {
		            summary.crkckslsum += Number(item.crkckslsum);
		        }
		    });
		
		    return summary;
		},
为什么使用 Set

Set 是 JavaScript 中的一种数据结构,类似于数组,但它只能存储唯一值。这意味着在 Set 中,重复添加的值会自动被忽略,这就非常适合用来跟踪和去除重复项。

具体作用

在这段代码中,uniqueValues 集合用来确保 crklrcssum 字段的值不会被重复累加。以下是实现逻辑:

  1. 检查唯一性:代码在 forEach 遍历中,通过 uniqueValues.has(item.crklrcssum) 检查 item.crklrcssum 是否已被处理。
  2. 避免重复累加:只有当 uniqueValues 中没有该值时,才将其累加到 summary.crklrcssum。这样即便 processedData 中包含多个相同的 crklrcssum 值,它们也只会被累加一次。
  3. 添加到 Set:在累加后,通过 uniqueValues.add(item.crklrcssum) 把当前的 crklrcssum 值加入 Set,确保后续遇到相同的值时不会再次累加。

3、插入合计行(我这里是要将后端返回的数据根据逗号分成一条一条的,如果你的后端返回的本来就是单条数据,则不用使用split分割)

processData(data) {
		    let result = [];
		    data.forEach(item => {
		        let crklycjArray = item.crklycjsum.split(',');
		        let crkckslArray = item.crkckslsum.split(',');
		        let crkbzArray = item.crkbzsum.split(',');
		        let crkbmArray = item.crkbmsum.split(','); // 处理部门数据
		        
		        if (item.crkbmsum.includes(',')) {
		            this.monthList.push(item.day); // 如果包含逗号,存储对应的 month
		        }
		        
		        const maxLength = Math.max(crklycjArray.length, crkckslArray.length, crkbzArray.length, crkbmArray.length);
		        
		        for (let index = 0; index < maxLength; index++) {
		            result.push({
		                day: item.day,
		                crklrcssum: item.crklrcssum,
		                crklycjsum: crklycjArray[index] ? crklycjArray[index].trim() : '',
		                crkbmsum: crkbmArray[index] ? crkbmArray[index].trim() : '', // 处理部门数据
		                crkckslsum: crkckslArray[index] ? crkckslArray[index].trim() : '',
		                crkbzsum: crkbzArray[index] ? crkbzArray[index].trim() : '',
		            });
		        }
		    });
		    this.processedData = result;
			
			const summary = this.getSummary();
			
			    // 插入合计行
			    this.processedData.push({
			        day: '合计',
			        crklrcssum: summary.crklrcssum,
			        crklycjsum: '',
			        crkbmsum: '',
			        crkckslsum: summary.crkckslsum,
			        crkbzsum: '',
			    });
		},

三、自定义合计行(根据物料名称来显示多条合计)

 1、先自定义summary-method方法

 <el-table
                        border
                         :data="reportData"
                        style="width: 100%"
						:header-cell-style="{background:'#f5f7fa'}"
						 :span-method="spanRows"
						 :summary-method="getSummary"
                    >

2、这里暂时还不知道后端返回的数据结构,我前端先是这样定义的

 //报表数据
            reportData: [
                {
                    materialName: '硫酸',
                    number: 'A级',
                    inQuantities: {
                        lastPeriod: '19858.10',
						dayLevel:{
							putInStorage:'157.92',
							thatDayConfiguration:'',
						},
						monthLevel:{
							putInStorage:'1518.78',
							thatMonthConfiguration:'',
						}  
                    }],

3、 定义合计方法

①初始化每个字段

②对字段的累加格式化。调用 .toFixed(2) 将浮点数格式化为字符串形式,并保留两位小数(根据个人情况使用,我这里如果不用格式化,累加数值就会出现类似1456.0000002330的错误情况)

③!!!计算插入位置,将每种物料的“合计”插入到 reportData 的相应位置中

	 getSummary() {
	     const summaryMap = {}; // 用于存储每种物料的合计
	 
	     // 计算合计值
	     this.reportData.forEach(item => {
	         
	         // 确保每种物料都有一个初始化的合计对象
	         if (!summaryMap[item.materialName]) {
	             summaryMap[item.materialName] = {
	                 materialName: '小计',
	                 number: '小计',
	                 inQuantities: {
	                     lastPeriod: 0,
	                     dayLevel: {
	                         putInStorage: 0,
	                         thatDayConfiguration: 0,
	                     },
	                     monthLevel: {
	                         putInStorage: 0,
	                         thatMonthConfiguration: 0,
	                     }
	                 },
	                 outQuantities: {
	                     thatDay: 0,
	                     thatMonth: 0,
	                 },
	                 monthlyBalance: 0,
	             };
	         }
	 
	         // 累加当前物料的值
	         const summaryItem = summaryMap[item.materialName];
			 summaryItem.inQuantities.lastPeriod += parseFloat(item.inQuantities.lastPeriod || 0);
			 summaryItem.inQuantities.dayLevel.putInStorage += parseFloat(item.inQuantities.dayLevel.putInStorage || 0);
			 summaryItem.inQuantities.dayLevel.thatDayConfiguration += parseFloat(item.inQuantities.dayLevel.thatDayConfiguration || 0);
			 summaryItem.inQuantities.monthLevel.putInStorage += parseFloat(item.inQuantities.monthLevel.putInStorage || 0);
			 summaryItem.inQuantities.monthLevel.thatMonthConfiguration += parseFloat(item.inQuantities.monthLevel.thatMonthConfiguration || 0);
	         summaryItem.outQuantities.thatDay += parseFloat(item.outQuantities.thatDay || 0);
	         summaryItem.outQuantities.thatMonth += parseFloat(item.outQuantities.thatMonth || 0);
	         summaryItem.monthlyBalance += parseFloat(item.monthlyBalance || 0);

	
	     });
		// 格式化小计数据
		   Object.values(summaryMap).forEach(summaryItem => {
		       summaryItem.inQuantities.lastPeriod = parseFloat(summaryItem.inQuantities.lastPeriod).toFixed(2);
		       summaryItem.inQuantities.dayLevel.putInStorage = parseFloat(summaryItem.inQuantities.dayLevel.putInStorage).toFixed(2);
		       summaryItem.inQuantities.dayLevel.thatDayConfiguration = parseFloat(summaryItem.inQuantities.dayLevel.thatDayConfiguration).toFixed(2);
		       summaryItem.inQuantities.monthLevel.putInStorage = parseFloat(summaryItem.inQuantities.monthLevel.putInStorage).toFixed(2);
		       summaryItem.inQuantities.monthLevel.thatMonthConfiguration = parseFloat(summaryItem.inQuantities.monthLevel.thatMonthConfiguration).toFixed(2);
		       summaryItem.outQuantities.thatDay = parseFloat(summaryItem.outQuantities.thatDay).toFixed(2);
		       summaryItem.outQuantities.thatMonth = parseFloat(summaryItem.outQuantities.thatMonth).toFixed(2);
		       summaryItem.monthlyBalance = parseFloat(summaryItem.monthlyBalance).toFixed(2);
		   });
	 
	     // 将每种物料的合计汇总到一个数组中
	     const summaryArray = Object.values(summaryMap);
		 // this.reportData.push(...summaryArray);
			 
		 const insertPositions = []; // 用于记录插入位置
		
		    // 计算插入位置
		    Object.entries(summaryMap).forEach(([materialName]) => {
		        const lastIndex = this.reportData.reduce((acc, item, index) => {
		            return item.materialName === materialName ? index : acc;
		        }, -1);
		
		        if (lastIndex !== -1) {
		            insertPositions.push(lastIndex + 1); // 记录插入位置
		        }
		    });
		
		    // 按照插入位置插入小计
		    insertPositions.forEach((pos, index) => {
		        this.reportData.splice(pos + index, 0, summaryArray[index]);
		    });

	     // 返回只包含每种物料合计的数组
	     return summaryArray;  
	 },

 这里是详细的分步解释:

1. 记录每种物料的最后位置 (insertPositions 数组)

  • insertPositions:用于记录每种物料小计的插入位置。
  • Object.entries(summaryMap).forEach(...):遍历 summaryMap 中的每种物料,materialName 是物料名称。
  • lastIndex:找到 reportData 中该物料名称的最后一项位置。例如,如果 reportData 有多条记录属于同一物料,小计应该插入在最后一条记录的后面。
    • reduce() 函数的逻辑是遍历 reportData 中的每一项,如果 item.materialNamematerialName 相等,则将当前 index 赋值给 acc,即更新最后出现的位置。
  • 如果找到物料(lastIndex !== -1),就在 insertPositions 中记录插入位置 lastIndex + 1(即该物料最后一条记录的后面)。

2. 根据 insertPositions 插入小计

insertPositions.forEach(...):遍历 insertPositions 中每个插入位置 pos

  • pos + indexindex 是当前的插入次数,用来偏移插入位置,以确保每次插入不会影响后续插入位置的准确性。
  • summaryArray[index]:取 summaryArray 中对应的物料小计。

* Object.entries() 方法的原理:

Object.entries() 是 JavaScript 的一个标准方法,用来获取对象的键值对。它将对象的每个属性(即键值对)转换成一个数组中的 [key, value] 数组对,然后把这些 [key, value] 数组组合成一个新的数组返回。示例如下:

* .reduce 方法

array.reduce((accumulator, currentValue, index, array) => {...}, initialValue);

具体来说:

  1. accumulator(缩写为 acc:累加器,用于累积每次回调的返回值。这个值会在每次迭代中更新,并最终成为 .reduce 的返回值。
  2. currentValue(缩写为 item:当前被处理的数组元素。
  3. index:当前元素的索引,可选参数。
  4. array:被遍历的数组本身,也是一个可选参数。

 示例如下:

const numbers = [10, 20, 30];

const sum = numbers.reduce((acc, item, index, array) => {
    console.log(`累加器: ${acc}, 当前值: ${item}, 索引: ${index}, 数组: ${array}`);
    return acc + item;
}, 0);

console.log(sum);


//打印输出如下
累加器: 0, 当前值: 10, 索引: 0, 数组: [10, 20, 30]
累加器: 10, 当前值: 20, 索引: 1, 数组: [10, 20, 30]
累加器: 30, 当前值: 30, 索引: 2, 数组: [10, 20, 30]

四、合并行(目前还不懂,该代码是上面第一个示例表的)

spanRows({ row, column, rowIndex }) {
            const getCount = (prop) => this.processedData.filter(r => r[prop] === row[prop]).length;
        
            if (column.property === 'day' ) {
                const prevRow = this.processedData[rowIndex - 1];
                if (prevRow && prevRow[column.property] === row[column.property] && (prevRow.day === row.day )) {
                    return { rowspan: 0, colspan: 0 }; // 取消合并
                }
                const count = getCount(column.property);
                return { rowspan: count, colspan: 1 }; // 合并当前值的行
            }
            return { rowspan: 1, colspan: 1 }; // 默认不合并
        },

day 是你要合并行的这一列的名称,如:我要按日期合并行

processedData 是我table表数据存放的数组

五、el-date-picker默认日期设置 

1、年份选择器(type="year")

data() {
  return {
    filterConditionForm: {
      date: new Date(2023, 0, 1)  // 2023年
    }
  }
}

2、月份选择器(type="month")

data() {
  return {
    filterConditionForm: {
      date: new Date(2023, 5)  // 2023年6月
    }
  }
}

3、日期选择器(type="date")

data() {
  return {
    filterConditionForm: {
      date: new Date(2023, 5, 15)  // 2023年6月15日
    }
  }
}

4、日期时间选择器(type="datetime")

data() {
  return {
    filterConditionForm: {
      date: new Date(2023, 5, 15, 14, 30)  // 2023年6月15日 14:30
    }
  }
}

获取日期的常用方法:

  1. 获取年份:
    • getFullYear(): 返回四位数的年份(如 2023)
    • getYear(): 返回年份减去 1900(不推荐使用)
  2. 获取月份:
    • getMonth(): 返回月份(0-11,其中 0 表示一月)
  3. 获取日期:
    • getDate(): 返回月份中的第几天(1-31)
  4. 获取星期:
    • getDay(): 返回星期几(0-6,其中 0 表示星期日)
  5. 获取小时:
    • getHours(): 返回小时(0-23)
  6. 获取分钟:
    • getMinutes(): 返回分钟(0-59)
  7. 获取秒:
    • getSeconds(): 返回秒(0-59)
  8. 获取毫秒:
    • getMilliseconds(): 返回毫秒(0-999)
  9. 获取时间戳:
    • getTime(): 返回自 1970 年 1 月 1 日以来的毫秒数

此外,还有一些实用的方法来格式化和解析日期:

  1. 转换为字符串:
    • toDateString(): 返回日期部分的字符串
    • toTimeString(): 返回时间部分的字符串
    • toISOString(): 返回 ISO 格式的日期字符串
  2. 解析日期字符串:
    • Date.parse(): 解析日期字符串,返回时间戳

使用示例:

let now = new Date();

console.log("年份:", now.getFullYear());
console.log("月份:", now.getMonth() + 1);  // 注意要加1,因为月份从0开始
console.log("日期:", now.getDate());
console.log("星期:", now.getDay());
console.log("小时:", now.getHours());
console.log("分钟:", now.getMinutes());
console.log("秒:", now.getSeconds());

// 格式化日期
let year = now.getFullYear();
let month = (now.getMonth() + 1).toString().padStart(2, '0');  // 补零
let day = now.getDate().toString().padStart(2, '0');  // 补零
console.log(`格式化日期:${year}-${month}-${day}`);

 ps : 时间戳通常是一个很长的数字

六、el-table树状结构默认展开层数

5层结构我想要默认加载时只展开一层,如下图: 

①必要定义 row-key:expand-row-keys="expandRowKeys"

②初始化

③一定要转化为String类型!!!

第一步
<el-table
        v-loading="loading"
        :data="list"
        border
        size="mini"
        row-key="id"
        lazy
        :expand-row-keys="expandRowKeys"
        :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
      >
        <el-table-column label="ID" align="left" prop="id" width="140"/>
        <el-table-column label="分類名稱" align="left" prop="name"/>

第二步
 data() {
    return {
      expandRowKeys: []


第三步
getAllCategoriesTreeList(){
      this.loading = true
      getAllCategoriesTreeList({

      }).then((res)=>{
        this.loading = false
        if (res) {
          this.recursionStatusTextAndCls(res, 'children', this.availableOption)
          this.list = res

         this.$nextTick(() => {
           this.list.forEach(item => {
             this.expandRowKeys.push(String(item.id)); // 第一层展开,转字符串
             // if (item.children) {
             //   item.children.forEach(child => {
             //     this.expandRowKeys.push(String(child.id)); // 第二层展开,转字符串
             //   });
             // }
           });
         });
          }
      })
    },

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值