项目中我么有时候可以用到可以展开的表格树形表格,方便我们数据和层级关系。
效果图:
实现方式:递归组件思路,使用iview的表格https://www.iviewui.com/components/table#KZK
封装的组件:
src/views/commonComponents/ExpandTable/ExpandTable.vue
<template> <div :class="['ExpandTable', 'ExpandTableLevel'+ lev, {'no-table-header': lev !== 1}]"> <Table :class="['table', 'table-level-' + lev]" :loading="tableLoading" :columns="columnsIn" :data="tableData" @on-row-dblclick="handleRowDBclick"></Table> </div> </template> <script> // import util from '@/libs/util'; import ExpandTable from './ExpandTable.vue'; export default { name: 'ExpandTable', components: {ExpandTable}, /** * @on-update-complete 数据更新完成的 事件 ,配合 update props 可以做到 表格数据筛选, 在这个时间内 把 update字段 更改未 false * */ props: { //展开是接口 api: String, // row: Object, //展开时上级Id 的字段名称 parentIDFiled: { type: String, default: 'depId' }, id: String, // beginDate: String, // endDate: String, //层级(使用时这个props不用传) level: { type: Number, default: 0 }, //固定的请求参数 reqParam: { type: Object, default: ()=>({}) }, //表格列 columns: { type: Array, default: ()=>([]) }, update: Boolean, // false -> true 时更新 展开表格的数据 /** * 处理接口响应数据的函数, 主要是对接口响应的列表数据挂载 _disableExpand 字段 -> 为true 禁用展开(不显示前面的 展开符号) * @return 此函数必须 返回 表格数据 处理后表格的数据 * */ handleResFun: { type: Function, required: true } }, data(){ return { lev: 1, tableLoading: false, tableData: [], columnsIn: [ { type: 'expand', width: 50, render: (h, params) => { return h(ExpandTable, { props: { api: this.api, // id: params.row.depId, id: params.row[this.parentIDFiled], level: this.lev, // beginDate: this.beginDate, // endDate: this.endDate reqParam: this.reqParam, parentIDFiled: this.parentIDFiled, columns: this.columns, handleResFun: this.handleResFun } }) } }, ...this.columns ] } }, watch: { update(val){ val && this.lev === 1 && (this.getTableOfData()) } }, methods: { //表格行双击 展开与折叠 handleRowDBclick(row, index){ //禁用状态不能展开 if(row._disableExpand) return; if(this.tableData[index]['_expanded']){ this.$set(this.tableData[index], '_expanded', false); }else { this.$set(this.tableData[index], '_expanded', true); } }, //获取表格数据 getTableOfData(){ let that = this; this.tableLoading = true; this.$post(this.api, { [this.parentIDFiled]: this.id, ...this.reqParam }).then( response => { if (response.success) { /* response.data.list.forEach(item=> { //如果是人state '1' count '0' 没有子项 禁用展开、 if( item.state === '1' || item.count === '0' ) item._disableExpand = true }); that.tableData = response.data.list; */ that.tableData = this.handleResFun(response); } else { that.$Message.error(`查询失败:${response.msg}`); } that.tableLoading = false; this.$emit('on-update-complete') }).catch(error => { console.log('列表查询出错', error); }); }, }, created() { this.lev = this.level + 1; }, mounted () { // console.log(`显示第${this.lev}层数据`); this.getTableOfData(); } }; </script> <style scoped> .ExpandTable { background: #fff; } .ExpandTable >>> .table { border: none; margin-left: 30px; } .ExpandTable >>> .table .ivu-table-expanded-cell { background: #fff; padding: 0; } .ExpandTable.no-table-header >>> .table .ivu-table-header { display: none; } /*最外层边框*/ .ExpandTableLevel1 >>> .table-level-1.ivu-table-wrapper { position: relative; border: 1px solid #dcdee2; border-bottom: 0; /*border-right: 0;*/ overflow: hidden; } .ExpandTableLevel1 >>> .ivu-table-overflowX { overflow: unset; } .ExpandTableLevel1 >>> .table-level-1 { margin-left: 0; } /*所有子项下边线*/ /* .ExpandTable >>> .table .ivu-table::before { height: 0; } */ .ExpandTable >>> .table .ivu-table::after { width: 0; } .ExpandTable >>> .table .ivu-table td { border-bottom: none; } </style>
使用时:src/views/storeshop/stat/timeLimitStat.vue
<template> <div class="timeLimitStat wrapper_box"> <ExpandTable api="/pointStock/increment" parentIDFiled="depId" :columns="columns" :update="updateTable" :reqParam="{beginDate: formSearch.beginDate, endDate: formSearch.endDate}" :handleResFun="handleResDataFun" @on-update-complete="handleUpdateComplete"/> </div> </template> <script> import ExpandTable from '../../commonComponents/ExpandTable/ExpandTable'; export default { name: 'timeLimitStat', inject: ['export'], components: { ExpandTable }, data(){ return { //展开层级 // lev: 0, // tableData: [], //表格列定义 columns: [ { title: '部门', key: 'depName', }, { title: '期初', width: 400, key: 'beginPoint', }, { title: '期末', width: 400, key: 'endPoint', }, { title: '增量', width: 400, key: 'beginPoint', render: (h, params)=> h('span', Number(params.row.endPoint) - Number(params.row.beginPoint) ) }, ], updateTable: false, //是否更新 展开表格的数据 } }, methods: { // /pointStock/increment 接口数据处理函数 handleResDataFun(response){ response.data.list.forEach(item=> { //如果是人state '1' count '0' 没有子项 禁用展开、 if( item.state === '1' || item.count === '0' ) item._disableExpand = true }); return response.data.list; }, // 展开表格数据请求完毕的函数 handleUpdateComplete(){ this.updateTable = false; } }, created(){ this.computedTime(this.formSearch.timeArr); }, mounted () { } }; </script> <style scoped> .timeLimitStat >>> .ivu-table-expanded-cell { padding: 0; } </style>
效果图: