需求:表格存在多层父子级结构,要求点击父级行任意处都可以实时加载子级表格,并且只有最末一层子级可点击跳转,同级别的展开模式为手风琴模式❗❗(有点抽象的效果图如下所示:
思路:灵机一动😄这不就是量身打造的树形结构懒加载!只有有两个小点有些tricky:1)通过直接获取箭头的DOM元素来给整行响应点击事件;2)利用el-table展开行的回调expanded-change手动变为手风琴模式,即某行展开之后,同级别的其他行变为收起状态
渲染代码如下:
// ⚠树形结构的el-table必须存在row-key属性,父子级结构需存在相同的row-key绑定字段 <el-table :key="Math.random()" ref="table_1" :data="tableData1" row-key="acc_code" @row-click="showVoucher" lazy :load="loadNext" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" @expand-change="toggleRow" > <el-table-column label="科目" :show-overflow-tooltip="true" :resizable="false" min-width="200" > <template slot-scope="scope"> <span v-if="scope.row.idepth == '-1'"> <span class="has_underline" v-if="!scope.row.hasChildren">{{convertToChinaNum(scope.row.acc_code)}}、{{scope.row.acc_name}}</span> <span v-else>{{convertToChinaNum(scope.row.acc_code)}}、{{scope.row.acc_name}}</span> </span> <span v-else> <span class="has_underline" v-if="!scope.row.hasChildren">{{scope.row.acc_code}}-{{scope.row.acc_name}}</span> <span v-else>{{scope.row.acc_code}}-{{scope.row.acc_name}}</span> </span> </template> </el-table-column> <el-table-column label="年初余额" prop="" align="right" width="150"> </el-table-column> <el-table-column label="当月" align="center"> <el-table-column prop="" label="借方金额" :show-overflow-tooltip="true" :resizable="false" align="right" width="150"> </el-table-column> <el-table-column prop="" label="贷方金额" :show-overflow-tooltip="true" :resizable="false" align="right" width="150px"> </el-table-column> </el-table-column> <el-table-column label="累计" align="center"> <el-table-column prop="" label="借方金额" :show-overflow-tooltip="true" :resizable="false" align="right" width="150px"> </el-table-column> <el-table-column prop="" label="贷方金额" :show-overflow-tooltip="true" :resizable="false" align="right" width="150px"> </el-table-column> </el-table-column> <el-table-column label="当月余额" prop="" width="150" align="right"> </el-table-column> </el-table>
主要逻辑代码如下:
// 加载父级基础数据 loadExpCounts(){ axios({ method: 'post', url: '/', data: '...', }).then(response => { let resp = response.data; if(resp.success){ let exp_typeList = resp.objectMap.expTypeList || []; this.tableData1 = exp_typeList; this.tableData1.forEach(exp=>{ // 关闭所有子节点 this.$refs.table_1.toggleRowExpansion(exp, false); // 判断是否存在子级 if(exp.leaf_flag !== '1'){ this.$set(exp, 'hasChildren', true); } }) }else{ // ... } }).catch(error=> { }).finally(()=>{ }); }, // 懒加载下级表格 loadNext(tree, treeNode, resolve) { axios({ method: 'post', url: '/', data: { ajax: true, act: '', exp_type:tree.acc_code, }, }).then(response => { let resp = response.data; if(resp.success){ let expList = resp.objectMap.expList || []; expList.forEach(exp=>{ if(exp.leaf_flag !== '1'){ this.$set(exp, 'hasChildren', true); } }); resolve(expList); }else{} }).catch(error=> {}); },
1、行点击事件
// 行点击触发 showVoucher(row, column, event){ if(!row.hasChildren){ // 进入详情页 window.location = '...'; } else { // 展开下一级 event.currentTarget.querySelector('.el-table__expand-icon').click(); } },
2、同级别手风琴模式
// 手风琴模式 toggleRow(row, expanded){ const rowId = row.acc_code; const rowLevel = row.idepth; // 层级 if (!expanded) { return; } let list = this.levelData.get(rowLevel); if (!list) { list = []; } list.push(row); // 同层级存入 this.levelData.set(rowLevel, list); list.map(list => { if (list.acc_code !== rowId) { // 关闭同层级的其他行 this.$refs.table_1.toggleRowExpansion(list, false); } }); },
3、数字转中文汉字【来自网友记录一下❗】
// 数字转汉字 convertToChinaNum(num) { let arr1 = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; let arr2 = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千','万', '十', '百', '千','亿']; // 可继续追加更高位转换值 if(!num || isNaN(num)){ return "零"; } let english = num.toString().split(""); let result = ""; for (let i = 0; i < english.length; i++) { let des_i = english.length - 1 - i; // 倒序排列设值 result = arr2[i] + result; let arr1_index = english[des_i]; result = arr1[arr1_index] + result; } result = result.replace(/零(千|百|十)/g, '零').replace(/十零/g, '十'); result = result.replace(/零+/g, '零'); result = result.replace(/零亿/g, '亿').replace(/零万/g, '万'); result = result.replace(/亿万/g, '亿'); result = result.replace(/零+$/, ''); result = result.replace(/^一十/g, '十'); return result; },
至此大功告成😉