vue+ElementUI更像Excel的表格组件使用详解

 更新时间:2025年12月17日 15:57:39   作者:我的心巴  
这篇文章主要介绍了如何在前端处理表格数据并展示在Element UI的el-table组件中,核心思想是先构建表头和第一列,然后根据表头和第一行的数据填充表格内容

一、表格效果

二、核心思想

不做前端的人,会觉得“一”中图展示的就是一张表格;做前端的,看完“四”中注释的业务逻辑(可能看不懂,但无所谓,业务逻辑嘛,重要的是处理思想),会更觉得像Excel,自然也就不能直接将“三”中数据赋给el-table。

处理的核心思想就是先处理出表头(列prop赋值为顺序排列的小写字母)、第一列,再根据每一列的表头和第一行的数据找出填充的值(有点像直接坐标系,表头为X轴,第一列为Y轴)。

三、数据格式

四、组件代码

<template>
    <div>
        <div v-for="(table, index) in tables" :key="'table'+index" class="tables">
            <el-tag size="medium" effect="dark">{{ table.name }}</el-tag>
            <el-table :data="table.dataSource" border>
                <el-table-column v-for="column in table.columns" :key="'table'+index+column.prop" :prop="column.prop" :label="column.label" :min-width="column.minWidth" :align="column.align" :show-overflow-tooltip="column.tooltip"></el-table-column>
            </el-table>
        </div>
    </div>
</template>
<script>
export default {
    props: {
        params: {
            type: Object,
            default () {
                return {
                        tempCheck: [],
                        temperatureCompensation: [],
                        linear: [],
                        linearCheck: []
                }
            }
        }
    },
    computed: {
        tables () {
            let tables = [
                {
                    //表格名称
                    name: '温补结果',
                    //表格列,数据未处理之前写死在columns中的是固定列,其余列根据需求及数据处理而来
                    columns: [ //其余列是数据里不重复的pressPoint字段值+单位kPa
                        {
                            prop: 'a',
                            label: '温度℃', //列数据为不重复的temperaturePoint值
                            minWidth: 100,
                            align: 'center'
                        },
                        {
                            prop: 'b',
                            label: '温度AD', //只和温度temperaturePoint有关,列数据为不同temperaturePoint对应的temperatureAD值
                            minWidth: 100,
                            align: 'center'
                        }
                    ],
                    //表格数据,展示temperaturePoint和pressPoint对应的pressAD,数据来源params.temperatureCompensation
                    dataSource: []
                },
                {
                    name: '线性化结果',
                    columns: [], //不重复的pressPoint字段值+单位kPa
                    dataSource: [{}] //只会有一行数据,展示pressPoint对应的pressAD,    数据来源params.linear
                },
                {
                    name: '温补校验结果',
                    columns: [ //其余列是数据里不重复的temperaturePoint+单位℃
                        {
                            prop: 'a',
                            label: '压力', //列数据为不重复的pressPoint
                            minWidth: 100,
                            align: 'center'
                        }
                    ],
                    dataSource: [] //展示temperaturePoint和pressPoint对应的press,数据来源params.tempCheck
                },
                {
                    name: '线性化校验结果',
                    columns: [], //不重复的pressPoint字段值+单位kPa
                    dataSource: [{}] //只会有一行数据,展示pressPoint对应的press,数据来源params.linearCheck
                }
            ],
//根据tables注释的业务逻辑开始处理数据
columns = this.getXYNoRepeatData('temperatureCompensation', 'pressPoint').map((li, index) => {
                return {
                    prop: String.fromCharCode(99+index),
                    label: li+'kPa',
                    minWidth: 100,
                    align: 'center'
                }
            }), dataSource = this.getXYNoRepeatData('temperatureCompensation', 'temperaturePoint').map(li => {
                return {
                    a: li,
                    b: this.getADColumn('temperatureCompensation', li, 'temperaturePoint', 'temperatureAD')
                };
            }), errorRateList = [], errorRate = '', errorRateRrop = '';
            columns.forEach(column => {
                dataSource.forEach(d => {
                    Object.assign(d, {
                        [column.prop]: this.getValueByXY('temperatureCompensation', column.label.replace('kPa', ''), d.a, 'pressPoint', 'temperaturePoint', 'pressAD')
                    });
                });
            });
            tables[0].columns = tables[0].columns.concat(columns);
            tables[0].dataSource = dataSource; //完成温补结果columns、dataSource计算

            //计算线性化结果columns、dataSource
            columns = this.getXYNoRepeatData('linear', 'pressPoint').map((li, index) => {
                return {
                    prop: String.fromCharCode(97+index), //列prop处理为顺序排列的小写英文字母
                    label: li+'kPa',
                    minWidth: 100,
                    align: 'center'
                }
            });
            tables[1].columns = columns;
            columns.forEach(column => {
                Object.assign(tables[1].dataSource[0], {
                    [column.prop]: this.getValueByX('linear', column.label.replace('kPa', ''), 'pressPoint', 'pressAD')
                });
            });

            //计算温补校验结果columns、dataSource
            columns = this.getXYNoRepeatData('tempCheck', 'temperaturePoint').map((li, index) => {
                return {
                    prop: String.fromCharCode(98+index),
                    label: li+'℃',
                    minWidth: 100,
                    align: 'center'
                }
            });
            dataSource = this.getXYNoRepeatData('tempCheck', 'pressPoint').map(li => {
                return {
                    a: li+'kPa'
                };
            });
            columns.forEach(column => {
                dataSource.forEach(d => {
                    Object.assign(d, {
                        [column.prop]: this.getValueByXY('tempCheck', column.label.replace('℃', ''), d.a.replace('kPa', ''), 'temperaturePoint', 'pressPoint', 'press')
                    });
                });
            });
            errorRateRrop = String.fromCharCode(98+columns.length);
            columns.push({ //固定最后一列
                prop: errorRateRrop,
                label: '最大误差%', //列数据为每行temperaturePoint、pressPoint对应的errorRate的最大值
                minWidth: 100,
                align: 'center'
            });
            dataSource.forEach(d => {
                errorRateList = [];
                for(let i=0; i<columns.length-1; i++) {
                    errorRate = this.getValueByXY('tempCheck', columns[i].label.replace('℃', ''), d.a.replace('kPa', ''), 'temperaturePoint', 'pressPoint', 'errorRate');
                    errorRate===''?'':errorRateList.push(errorRate);
                }
                if(errorRateList.length>0) {
                    errorRateList.sort((a, b) => {
                        return b-a;
                    });
                    Object.assign(d, {
                        [errorRateRrop]: errorRateList[0]
                    });
                } else {
                    Object.assign(d, {
                        [errorRateRrop]: ''
                    });
                }
            });
            tables[2].columns = tables[2].columns.concat(columns);
            tables[2].dataSource = dataSource;

            //计算线性化校验结果columns、dataSource
            columns = this.getXYNoRepeatData('linearCheck', 'pressPoint').map((li, index) => {
                return {
                    prop: String.fromCharCode(97+index),
                    label: li+'kPa',
                    minWidth: 100,
                    align: 'center'
                }
            });
            columns.forEach(column => {
                Object.assign(tables[3].dataSource[0], {
                    [column.prop]: this.getValueByX('linearCheck', column.label.replace('kPa', ''), 'pressPoint', 'press')
                });
            });
            errorRateRrop = String.fromCharCode(97+columns.length);
            columns.push({
                prop: errorRateRrop,
                label: '最大误差%',
                minWidth: 100,
                align: 'center'
            });
            errorRateList = this.params.result.linearCheck.map(li => {
                return li.errorRate;
            }).sort((a, b) => {
                return b-a;
            });
            Object.assign(tables[3].dataSource[0], {
                [errorRateRrop]: errorRateList.length>0?errorRateList[0]:''
            });
            tables[3].columns = columns;
            return tables;
        }
    },
    methods: {
        getXYNoRepeatData (vari, variable) {
            let arr = this.params[vari].map(li => {
                return li[variable];
            }).sort((a, b) => {
                return a-b;
            }), set = new Set(arr);
            return Array.from(set.values());
        },
        getADColumn (vari, val, valueField, labelField) {
            let item = this.params[vari].find(li => li[valueField]===val);
            return item?item[labelField].toFixed(1):'';
        },
        getValueByXY (vari, x, y, xField, yField, valueField) {
            let item = this.params[vari].find(li => li[xField]==x&&li[yField]==y);
            return item?item[valueField].toFixed(valueField.includes('AD')?1:3):'';
        },
        getValueByX (vari, x, xField, valueField) {
            let item = this.params[vari].find(li => li[xField]==x);
            return item?item[valueField].toFixed(valueField.includes('AD')?1:3):'';
        }
    }
}
</script>
<style scoped>
.tables >>>.el-tag {
    margin: 20px 0 10px 0;
}
</style>

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue如何设置描点跳转到对应页面

    vue如何设置描点跳转到对应页面

    这篇文章主要介绍了vue如何设置描点跳转到对应页面问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-05-05
  • vue cli使用融云实现聊天功能的实例代码

    vue cli使用融云实现聊天功能的实例代码

    最近小编接了一个新项目,项目需求要实现一个聊天功能,今天小编通过实例代码给大家介绍vue cli使用融云实现聊天功能的方法,感兴趣的朋友跟随小编一起看看吧
    2019-04-04
  • Vue组件层级关系详细分析

    Vue组件层级关系详细分析

    这篇文章主要介绍了Vue组件的层级关系,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Vue如何根据角色获取菜单动态添加路由

    Vue如何根据角色获取菜单动态添加路由

    这篇文章主要介绍了Vue如何根据角色获取菜单动态添加路由,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • 利用Vue实现将图片转换为Base64编码的方法

    利用Vue实现将图片转换为Base64编码的方法

    这篇文章主要介绍了利用Vue实现将图片转换为Base64编码的方法,Base64是一种编码方式,用于将二进制数据转换成64个基于ASCII的可打印字符,这种编码可嵌入图像到HTML或CSS中,减少加载时间,解决跨域问题,并支持离线应用开发,需要的朋友可以参考下
    2024-10-10
  • vue实现标签页切换/制作tab组件详细教程

    vue实现标签页切换/制作tab组件详细教程

    在项目开发中需要使用vue实现tab页签切换功能,所以这里总结下,这篇文章主要给大家介绍了关于vue实现标签页切换/制作tab组件的相关资料,需要的朋友可以参考下
    2023-11-11
  • Vue.js 实现tab切换并变色操作讲解

    Vue.js 实现tab切换并变色操作讲解

    这篇文章主要介绍了Vue.js 实现tab切换并变色操作讲解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • vue-cli脚手架搭建的项目去除eslint验证的方法

    vue-cli脚手架搭建的项目去除eslint验证的方法

    今天小编就为大家分享一篇vue-cli脚手架搭建的项目去除eslint验证的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 面试最常问的13种Vue修饰符

    面试最常问的13种Vue修饰符

    修饰符也是Vue的重要组成成分之一,利用好修饰符可以大大地提高开发的效率,接下来给大家介绍一下面试官最喜欢问的13种Vue修饰符,感兴趣的可以了解一下
    2021-07-07
  • Vue+Element-UI实现上传图片并压缩

    Vue+Element-UI实现上传图片并压缩

    这篇文章主要为大家详细介绍了Vue+Element-UI实现上传图片并压缩功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11

最新评论