Vue+el-table实现不规则表格

简介: Vue+elemenntUI

比如:我们要实现下图这个表格
在这里插入图片描述
代码如下:

<template>
  <div>
    <el-table :data="tableData" :span-method="objectSpanMethod" border :header-cell-style="handerMethod">
      <el-table-column align="center" prop="id" label=""></el-table-column>
      <el-table-column align="center" prop="amount1" label="数据分类"></el-table-column>
      <el-table-column align="center" prop="amount2" label="缴存业务"></el-table-column>
      <el-table-column align="center" prop="amount3" label="提取业务"></el-table-column>
      <el-table-column align="center" prop="amount4" label="贷款业务"></el-table-column>
      <el-table-column align="center" label="业务办理合计">
        <el-table-column align="center" label="业务办理合计" prop="amount5"></el-table-column>
        <el-table-column align="center" label="" prop="amount6"></el-table-column>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      spanArr: [], // 用于存放每一行记录的合并数
      tableData: [
        {
          id: '业务办理类业务统计量',
          amount1: '线上服务量小计',
          amount2: '1',
          amount3: '2',
          amount4: '3',
          amount5: '4',
          amount6: '4'
        },
        {
          id: '业务办理类业务统计量',
          amount1: '线上业务小计',
          amount2: '1',
          amount3: '2',
          amount4: '3',
          amount5: '4',
          amount6: '4'
        },
        {
          id: '业务办理类业务统计量',
          amount1: '线下业务小计',
          amount2: '1',
          amount3: '2',
          amount4: '3',
          amount5: '4',
          amount6: '4'
        },
        {
          id: '业务办理类业务统计量',
          amount1: '线上+线下',
          amount2: '1',
          amount3: '2',
          amount4: '3',
          amount5: '4',
          amount6: '4'
        },
        {
          id: '业务办理类业务统计量',
          amount1: '线上占比',
          amount2: '1',
          amount3: '2',
          amount4: '3',
          amount5: '4',
          amount6: '4'
        },
        {
          id: '9大渠道服务总量统计',
          amount1: '9大渠道服务总量统计',
          amount2: '信息查询',
          amount3: '信息发布',
          amount4: '互动交流',
          amount5: '业务办理',
          amount6: '线上总计'
        },
        {
          id: '9大渠道服务总量统计',
          amount1: '9大渠道服务总量统计',
          amount2: '01',
          amount3: '02',
          amount4: '03',
          amount5: '04',
          amount6: '05'
        }
      ]
    }
  },
  mounted() {
  },
  methods: {
    // 隐藏表头
    handerMethod({ rowIndex }) {
      if (rowIndex === 1) {
        // 这里为了是将第二列的表头隐藏,就形成了合并表头的效果
        return { display: 'none' }
      }
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      // 对第六、七行 进行合并
      if (rowIndex === 5) {
        if (columnIndex === 0) {
          return [2, 2]
        } else if (columnIndex === 1) {
          return [0, 0]
        }
      }
      // 对第一列 第二列 进行合并
      if (columnIndex === 1 || columnIndex === 0) {
        // 当 当前行与上一行内容相同时 返回0 0 意味消除
        if (rowIndex > 0 && row[column.property] === this.tableData[rowIndex - 1][column.property]) {
          return {
            rowspan: 0,
            colspan: 0
          }
        } else {
          let rows = 1
          // 反之 查询相同的内容有多少行 进行合并
          for (let i = rowIndex; i < this.tableData.length - 1; i++) {
            if (row[column.property] === this.tableData[i + 1][column.property]) {
              rows++
            }
          }
          // 返回相同内容的行数
          return {
            rowspan: rows,
            colspan: 1
          }
        }
      }
      // 对第一、二、三、四、五行 进行合并
      if (rowIndex === 0 || rowIndex === 1 || rowIndex === 2 || rowIndex === 3 || rowIndex === 4) {
        // 处理合计,[1,2]表示合并1行2列,[0,0]表示改行不显示
        if (columnIndex === 5) {
          // 定位到5列的一、二、三、四、五行,告诉该单元格合并1行2列
          return [1, 2]
        } else if (columnIndex === 6) {
          // 定位到6列的一、二、三、四、五行,告诉该单元格不显示
          return [0, 0]
        }
      }
    }

  }
}
</script>

el-table 行合并

方法一:(直接使用)

<el-table
                :data="tableData"
                border
                :span-method="objectSpanMethod"
                style="width: 100%">
                <el-table-column
                prop="order"
                label="序号"
                align="center"
                width="50">
                </el-table-column>
                <el-table-column
                prop="name"
                :label="'名称'"
                align="center"
                fixed="left"
                width="70">
                </el-table-column>
</el-table>



<script>
export default {
  name: 'StationsStaTable',
  data () {
    return {
        tableData: [],
    },
 methods: {
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
// 对第一列 第二列 进行合并
        if (columnIndex === 1 || columnIndex === 0) {
            // 当 当前行与上一行内容相同时 返回0 0 意味消除
            if(rowIndex > 0 && row[column.property] === this.tableData[rowIndex - 1][column.property]){
                return {
                    rowspan: 0,
                    colspan: 0
                };
            }else{
                let rows = 1;
                // 反之 查询相同的内容有多少行 进行合并
                for(let i = rowIndex; i < this.tableData.length - 1; i++){
                    if (row[column.property] === this.tableData[i + 1][column.property]) {
                        rows++;
                    }
                }
                // 返回相同内容的行数
                return {
                    rowspan: rows,
                    colspan: 1
                };
            }
        }
      }
 }

方法二:(封装函数)

1、使用

导入js文件,并设置需要合并的列

//导入js文件(文件脚本内容在下文)
import {getRowspanMethod} from '@/hook/el-tables/use-span-method.js'

//调用函数并导出需要的合并列函数 注意需要根据
//data为查询到的数据
//['prop1', 'prop2', 'prop3'] 需要合并的列
const spanMethod=getRowspanMethod(data,['prop1', 'prop2', 'prop3'])

在vue页面模板中使用

<!--使用spanMethod方法-->
<el-table :data="data" height="100%" :span-method="spanMethod">
...
</el-table>

2、封装合并的方法

这个文件(use-span-method.js)通过导出一个函数来提供给el-table的和并方法使用

/**
 * 合并相同数据,导出合并列所需的方法(只适合el-table)
 * @param {Object} data
 * @param {Object} rowspanArray
 */
export function getRowspanMethod(data, rowspanArray) {

    /**
     * 要合并列的数据
     */
    const rowspanNumObject = {};

    //初始化 rowspanNumObject
    rowspanArray.map(item => {
        rowspanNumObject[item] = new Array(data.length).fill(1, 0, 1).fill(0, 1);
        rowspanNumObject[`${item}-index`] = 0;
    });
    //计算相关的合并信息
    for (let i = 1; i < data.length; i++) {
        rowspanArray.map(key => {
            const index = rowspanNumObject[`${key}-index`];
            if (data[i][key] === data[i - 1][key]) {
                rowspanNumObject[key][index]++;
            } else {
                rowspanNumObject[`${key}-index`] = i;
                rowspanNumObject[key][i] = 1;
            }

        });
    }

    //提供合并的方法并导出
    const spanMethod = function({ row, column, rowIndex, columnIndex }) {
        if (rowspanArray.includes(column['property'])) {
            const rowspan = rowspanNumObject[column['property']][rowIndex];
            if (rowspan > 0) {
                return { rowspan: rowspan, colspan: 1 }
            }
            return { rowspan: 0, colspan: 0 }
        }
        return { rowspan: 1, colspan: 1 }
    };

    return spanMethod;
}

3、vue2/3具体使用

// vue2
import {getRowspanMethod} from '@/hook/el-tables/use-span-method.js'
    export default {
        data(){
            spanMethod:()=>{},
            list:[],
        },
        methods:{
            // 查询数据方法
            getData(){
                this.spanMethod=getRowspanMethod(this.list,['prop1', 'prop2', 'prop3'])
            }
        }
    }
 
// vue3 setup
import {ref ,computed} from 'vue';
    import {getRowspanMethod} from '@/hook/el-tables/use-span-method.js'
    
    // 获取数据存放变量
    let list=ref([]);
    //实际根据业务灵活调整
    const spanMethod=computed(()=>{
        return getRowspanMethod(list.value,['prop1', 'prop2', 'prop3'])
    })
    
    // 查询数据方法
    const getData=function(){
        //查询到数据赋值
        list.value=[];
    }

el-table 列合并

objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      // 处理合计,[1,2]表示合并2行2列,[0,0]表示改行不显示
      if (rowIndex === 5) {
        if (columnIndex === 0) {
          // 定位到0列,告诉该单元格合并1行2列
          return [1, 2]
        } else if (columnIndex === 1) {
           // 定位到1列,告诉该单元格不显示
          return [0, 0]
        }
      }
    }

el-table表头列合并

<el-table :data="tableData" :header-cell-style="handerMethod">
    <el-table-column align="center" label="业务办理合计">
            <el-table-column label="业务办理合计" prop="amount5"></el-table-column>
            <el-table-column label="" prop="amount6"></el-table-column>
          </el-table-column>
</el-table>
    //隐藏表头
    handerMethod({rowIndex}){
      if (rowIndex === 1) {
       //这里为了是将第二列的表头隐藏,就形成了合并表头的效果
        return {display: 'none'}
      }
    },
       <el-table-column label="业务办理合计" prop="amount5"></el-table-column>
        <el-table-column label="" prop="amount6"></el-table-column>
      </el-table-column>

//隐藏表头
handerMethod({rowIndex}){
  if (rowIndex === 1) {
   //这里为了是将第二列的表头隐藏,就形成了合并表头的效果
    return {display: 'none'}
  }
},
## el-table自定义合计

**效果图如下:**![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/8c9d932c73334f9a99671a300d7f5bb3.png)**代码实现:**

return {
  tableData: [
    {       
      name: '张三',
      sex: '男',
      tiZh: 120,
      num1: 1000,
      num2: 2000,
      num3: 3000
    },{       
      name: '张四',
      sex: '女',
      tiZh: 120,
      num1: 1000,
      num2: 2000,
      num3: 3000
    },
  ],
}

},
computed: {},
mounted() {},
methods: {

objectSpanMethod() {
  this.$nextTick(x => {
  if (this.$refs.table.$el) {
      var current = this.$refs.table.$el
        .querySelector(".el-table__footer-wrapper")
        .querySelector(".el-table__footer");
      var cell = current.rows[0].cells;
      cell[0].style.display = "none";
      cell[1].style.display = "none";
      cell[2].style.display = "none";
      cell[3].classList.remove('is-left')
      cell[3].colSpan = "4";
    }
  })
},
getNodeSummaries(param) {
  const { columns, data } = param;
  const sums = [];
  let arr = [ 'num1', 'num2', 'num3']
  columns.forEach((column, index) => {
    if (index === 3) {
      sums[index] = "合计";
      return;
    }
    if (arr.some(x => column.property === x)) {
      sums[index] = 0;
      data.map((item) => {
        console.log(item)
        let num = item[column.property];
        // num = num ? parseFloat(num.replace(/,/gi, "")) : 0;
        sums[index] = this.accAdd(sums[index], num);
      });
    } else {
      sums[index] = "";
    }
  });
  return sums;
},
accAdd(arg1, arg2) {
  let r1, r2, m;
  try {
    r1 = arg1.toString().split(".")[1].length;
  } catch (e) {
    r1 = 0;
  }
  try {
    r2 = arg2.toString().split(".")[1].length;
  } catch (e) {
    r2 = 0;
  }
  m = Math.pow(10, Math.max(r1, r2));
  return ((arg1 * m + arg2 * m) / m).toFixed(2);
},

}
}

width: 50%;
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

}

目录
相关文章
|
2天前
|
JavaScript
|
1天前
|
存储 缓存 JavaScript
vue代码优化方案
【7月更文挑战第13天】 **Vue.js 优化要点:** 分解大组件以提高复用性和加载速度;利用计算属性与侦听器优化数据处理;使用Object.freeze()减少响应式数据;借助Vuex或Composition API管理状态;实现虚拟滚动和无限加载提升长列表性能;路由懒加载减少初始加载时间;用Vue DevTools检测性能瓶颈;定期代码审查与重构;应用缓存策略;遵循最佳实践与团队规范,提升应用整体质量。
10 2
|
4天前
|
JavaScript 前端开发
【vue】 el-table解决分页不能筛选全部数据的问题
【vue】 el-table解决分页不能筛选全部数据的问题
15 4
|
4天前
|
JavaScript
【vue】 vue2 监听滚动条滚动事件
【vue】 vue2 监听滚动条滚动事件
10 1
|
4天前
|
JavaScript 定位技术
【天地图】vue 天地图 T is not defined
【天地图】vue 天地图 T is not defined
15 1
|
4天前
|
JavaScript
【vue】el-dialog 内的tinymce弹窗被遮挡的解决办法 及 tinymce打开弹出菜单后直接关闭对话组件,导致该弹出菜单残留
【vue】el-dialog 内的tinymce弹窗被遮挡的解决办法 及 tinymce打开弹出菜单后直接关闭对话组件,导致该弹出菜单残留
16 6
|
9天前
|
数据采集 JavaScript 前端开发
Vue框架的优缺点是什么
【7月更文挑战第5天】 Vue框架:组件化开发利于重用与扩展,响应式数据绑定简化状态管理;学习曲线平缓,生态系统丰富,集成便捷,且具性能优化手段。缺点包括社区规模相对小,类型支持不足(Vue 3.x改善),路由和状态管理需额外配置,SEO支持有限。随着发展,部分缺点正被克服。
19 1
|
10天前
|
JavaScript
Vue卸载eslint的写法,单独安装eslint,单独卸载eslint
Vue卸载eslint的写法,单独安装eslint,单独卸载eslint
|
10天前
|
JavaScript
青戈大佬安装Vue,无Eslint安装版,vue2安装,vue2无eslint,最简单配置Vue安装资料
青戈大佬安装Vue,无Eslint安装版,vue2安装,vue2无eslint,最简单配置Vue安装资料
|
4天前
|
JavaScript 前端开发
【vue】 Tinymce 数据 回显问题 | 第一次正常回显后面,显示空白bug不能编辑
【vue】 Tinymce 数据 回显问题 | 第一次正常回显后面,显示空白bug不能编辑
11 0