vue使用el-table筛选tree树形结构的数据问题
作者:蜂巢糖FCT
这篇文章主要介绍了vue使用el-table筛选tree树形结构的数据问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
实现难点
1.对于普通列数据el-table表格可做到多条件筛选,但是对于带tree树形结构类型的数据只能筛选到最上层节点,子节点不会筛选
2.考虑到缺陷,因此查看文档只能通过文档提供的filter-change事件手动筛选数据。
思路
1.通过filter-change事件使用filterObj对象保存点击的筛选状态
2.先将当前树形数据转变成普通列数据,再进行手动过滤,过滤后以 普通列数据展示
3.当无筛选条件时再以树形结构展示
图例
实现步骤
1.数据初始化
data:{ return{ targetNode:{},//总数据,保持tree数据类型 tableData:[],//展示在table上的数据 filterObj:{isEnable:[],filterTypeAttr:[],filterTypeCondition:[]},//过滤条件,由于表 格组件filterchange方法只会提示当前的筛选项, //所以使用filterObj来保存所有筛选过的选项 } }
2.表格
<el-table :data="tableData" row-key="id" border default-expand-all v-loading="loading" @filter-change="filterChange" ref="filterTable" :tree-props="{children: 'children', hasChildren: 'hasChildren'}"> <el-table-column prop="index" label="顺序" width="180"> <template slot-scope="scope">{{(scope.$index + 1)}}</template> </el-table-column> <el-table-column prop="filterName" label="筛选项" width="180"> <template slot-scope="scope"><span :class=" [scope.row.filterTypeCondition==1?'filter-name':'']">{{ scope.row.filterName }} </span><i v-if="scope.row.filterTypeAttr!==2" class="el-icon-plus" style="color: #03a9f4;font-size: 12px;margin-left: 10px;cursor: pointer;" @click="addCondition(scope.row)"></i> </template> </el-table-column> <el-table-column prop="filterTypeAttr" column-key="filterTypeAttr" :filters="[{ text: '自定义', value: '1' }, { text: '机构名称', value: '2'},{ text: '无', value: ''}]" label="筛选类型属性"> <template slot-scope="scope">{{ scope.row.filterTypeAttr==1?'自定义': scope.row.filterTypeAttr==2?'机构名称':''}}</template> <template slot="header" slot-scope="scope"> <!-- {{filterObj.filterTypeAttr.length==0?'筛选类型属 性':filterObj.filterTypeCondition.length==1 && filterObj.filterTypeCondition[0]==1?'1-筛选类型' :filterObj.filterTypeCondition.length==1 && filterObj.filterTypeCondition[0]==2?'2-筛选条件':'筛选类型属性-全部'}} --> {{filterObj.filterTypeAttr.length==3?'筛选类型属性-全部':'筛选类型 属性'+(filterObj.filterTypeAttr.includes(1)?'-自定义':'')+ (filterObj.filterTypeAttr.includes(2)?'-机构名称':'')+ (filterObj.filterTypeAttr.includes(0)?'-无':'')}} </template> </el-table-column> <el-table-column prop="filterTypeCondition" column-key="filterTypeCondition" :filters="[{ text: '1-筛选类型', value: '1' }, { text: '2-筛选条件', value: '2'}]" label="标识"> <template slot-scope="scope">{{ scope.row.filterTypeCondition==1?'1-筛选类型':'2-筛选条件'}}</template> <template slot="header" slot-scope="scope"> {{filterObj.filterTypeCondition.length==0?'标识':filterObj.filterTypeCondition.length==1 && filterObj.filterTypeCondition[0]==1?'标识-1-筛选类型':filterObj.filterTypeCondition.length==1 && filterObj.filterTypeCondition[0]==2?'标识-2-筛选条件':'标识-全部'}} </template> </el-table-column> <el-table-column prop="defaultSelected" label="是否属于默认展示项"> <template slot-scope="scope"> {{scope.row.defaultSelected==1?'是':scope.row.defaultSelected==0?'否':''}} </template> </el-table-column> <el-table-column prop="action" label="操作" width="250"> <template slot-scope="scope"> <span v-if="scope.row.filterTypeCondition==2" class="scope-span" :class=" [scope.row.rule && scope.row.rule!=''?'filter-span':'']" @click="showRegular(scope.row)">规则式</span> <span class="scope-span" @click="updateFilter(scope.row)">编辑</span> <el-popconfirm title="是否确定删除?" @confirm="delFilter(scope.row)" > <span class="scope-span" slot="reference" >删除</span> </el-popconfirm> </template> </el-table-column> <el-table-column prop="isEnable" label="状态" column-key="isEnable" :filters="[{ text: '启用', value: '1' }, { text: '禁用', value: '0' }]" > <template slot-scope="scope">{{ scope.row.isEnable==1?'启用':'禁用'}}</template> <template slot="header" slot-scope="scope"> {{filterObj.isEnable.length==0?'状态' :filterObj.isEnable.length==1 && filterObj.isEnable[0]==1?'状态-启用' :filterObj.isEnable.length==1 && filterObj.isEnable[0]==0?'状态-禁用':'状态-全部'}} </template> </el-table-column> </el-table>
要点:
default-expand-all
:默认展开全部子节点filterChange
:获取点击的筛选条件状态,对应列表头上设置:filters属性的列
<template slot="header" slot-scope="scope">设置筛选后用来替换表头的label内容
3.filterChange函数
filterChange(filters){//触发过滤事件时过滤数据 console.log('filters',filters); if(filters['isEnable']){ this.filterObj['isEnable'] = filters['isEnable'].map(Number); } if(filters['filterTypeAttr']){ this.filterObj['filterTypeAttr'] = filters['filterTypeAttr'].map(Number); } if(filters['filterTypeCondition']){ this.filterObj['filterTypeCondition'] = filters['filterTypeCondition'].map(Number); } if(this.filterObj['isEnable'].length==0 && this.filterObj['filterTypeAttr'].length==0 && this.filterObj['filterTypeCondition'].length==0){ this.tableData = this.targetNode.filterList; }else{ let dataList = []; this.targetNode.filterList.forEach(item=>{//层级数据转变成普通列数据 let obj = { filterName:item.filterName, filterTypeAttr:item.filterTypeAttr, sort:item.sort, isEnable:item.isEnable, columnId:item.columnId, id:item.id, filterTypeCondition:1, index:item.index } dataList.push(obj); if(item.children){ dataList = dataList.concat(this.getLineData(item.children)) } }) console.log('线性数据',dataList); if(this.filterObj['isEnable'].length>0){//状态 dataList = dataList.filter(item=>{ return this.filterObj['isEnable'].includes(item.isEnable) }) } if(this.filterObj['filterTypeCondition'].length>0){//标识 dataList = dataList.filter(item=>{ return this.filterObj['filterTypeCondition'].includes(item.filterTypeCondition) }) } if(this.filterObj['filterTypeAttr'].length>0){//属性 console.log('11',this.filterObj['filterTypeAttr']); dataList = dataList.filter(item=>{ return this.filterObj['filterTypeAttr'].includes(item.filterTypeAttr?item.filterTypeAttr:0) }) } console.log('过滤数据',dataList); this.tableData = dataList; } }, getLineData(data){//层级数据变成行数据 let list = []; data.forEach(item=>{ let obj = {}; if(item.filterTypeCondition==1){//筛选类型 obj = { filterName:item.filterName, filterTypeAttr:item.filterTypeAttr, sort:item.sort, isEnable:item.isEnable, parentId:item.parentId, id:item.id, filterTypeCondition:1, index:item.index } }else{ obj = { filterName:item.filterName, sort:item.sort, isEnable:item.isEnable, parentId:item.parentId, id:item.id, defaultSelected:item.defaultSelected, filterTypeCondition:2, index:item.index } } list.push(obj); if(item.children){ list = list.concat(this.getLineData(item.children)) } }) return list; },
步骤
- 1.fiters参数为当前点击的筛选项,数据结构如下:
- 2.使用filterObj保存当前筛选状态,筛选重置时为[]空数组
- 3.保存后判断filterObj各项是否都是空数组,是则直接赋值
- 4.否则将树形结构转换成普通列数据,注意考虑浅克隆的问题,getLineData函数作用是将子节点children也插入到普通列中
- 5.数据转换成普通列数据后进行过滤
实现效果
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。