TNBLOG
首页
博客
视频
资源
问答
猿趣
手机
关于
搜索
收藏
便签
笔记
消息
创作
登录
剑轩
应无所住,而生其心
博主信息
排名
6
文章
6
粉丝
16
评论
8
文章类别
CSS
16篇
微服务
41篇
Git
15篇
.NET
104篇
移动开发
33篇
软件架构
23篇
.NET Core
119篇
.NET MVC
11篇
英语
3篇
随笔
90篇
Bootstrap
3篇
Redis
21篇
编辑器
10篇
Js相关
15篇
虚拟化
8篇
更多
Oracle
7篇
Python
14篇
数据库
26篇
EF
17篇
微信
3篇
前端
160篇
消息队列
6篇
docker
41篇
多线程
1篇
Java
4篇
软件基础
2篇
C++
2篇
WCF
7篇
Linux
7篇
nginx
5篇
K8S
9篇
ABP
2篇
最新文章
最新评价
{{item.articleTitle}}
{{item.blogName}}
:
{{item.content}}
关于我们
ICP备案 :
渝ICP备18016597号-1
网站信息:
2018-2024
TNBLOG.NET
技术交流:
群号656732739
联系我们:
contact@tnblog.net
欢迎加群
欢迎加群交流技术
原
ElementUI Table 动态表头,动态数据,动态列
1474
人阅读
2024/5/13 11:50
总访问:
4427971
评论:
0
收藏:
0
手机
分类:
前端
表格显示的列不确定的时候就需要使用动态的方式,而不是预先绑定好。 [TOC] ## 前端的实现 #### 数据源 对于前端来说数据源和前面的一样,没什么区别,反正就是提供一下数据 ``` const data = [ { name: 'John Doe', age: 30, city: 'New York' }, { name: 'Jane Smith', age: 25, city: 'London' }, { name: 'Michael Jones', age: 40, city: 'Paris' } ]; ``` #### 动态表头 表头就不能写死了,需要绑定的来,相当于列就是动态的显示的,不是预先绑定好的 ``` const columns = [ { prop: 'name', label: '姓名' }, { prop: 'age', label: '年龄' }, { prop: 'city', label: '城市' } ]; ``` 然后这样绑定上去就可以动态的渲染出来表头了 ``` <el-table :data="data" :columns="columns"></el-table> ``` 上面那个不好写一些额外的列,比如还有一些固定的列和编辑列这种,所以可以把需要动态显示的列循环出来 ``` <el-table :data="state.tableData" v-loading="state.tableLoading" :header-cell-style="{ background: '#f8f8f9' }" style="width: 100%;margin-top:-10px"> <el-table-column prop="className" label="班级" show-overflow-tooltip min-width="219" /> <el-table-column prop="studentCount" sortable label="学生数" align="center" min-width="119" /> <!-- 循环出来需要动态显示的列 --> <el-table-column :label="item.label" min-width="139" :prop="item.prop" v-bind:key="index" v-for="(item, index) in state.dynamicColumns"> </el-table-column> <el-table-column header-align="center" align="center" label="操作" width="90px" fixed="right"> <template #default="scope"> <el-link :underline="false" @click="showDetails(scope.row)" type="primary">详情</el-link> </template> </el-table-column> </el-table> ``` ## 后端的实现 需要提供动态的数据源和动态的表头,c# 可以使用ExpandoObject 构建动态类型 #### 后台需要的相关实体 动态表头需要的实体 ``` public class ElementTableColumn { public string prop { get; set; } public string label { get; set; } } ``` 接口需要返回的实体 ``` public class ElementTableDynamic { /// <summary> /// 动态表头 /// </summary> public List<ElementTableColumn> Columns { get; set; } /// <summary> /// 动态数据 /// </summary> public List<ExpandoObject> Data { get; set; } } ``` #### 动态构建数据的逻辑 这里主要贴的是动态构建数据的逻辑,具体的业务逻辑需要换成自己的 ``` public ElementTableDynamic ClassMonthTaskReport(ClassStatisticsParams _params) { // 这里边是需要显示动态数据的 List<Tasks> tasks = BaseDal.Db.Queryable<Tasks>().OrderBy(a => a.OrderNum).OrderBy(a => a.CreateTime).Take(_params.TakeCount).ToList(); // 其他逻辑..... // 构建动态的表头 List<ElementTableColumn> elementTableColumns = new List<ElementTableColumn>(); foreach (Tasks taskItem in tasks) { ElementTableColumn elementTableColumn = new ElementTableColumn(); // elementTableColumn.label = taskItem.TaskName; // 列名显示这个短名称吧 elementTableColumn.label = taskItem.ReportName; // 动态列名,用id来拼一个名称,显示的可能会随时调整(当然也可以在数据库单独创建一列来存储一个列名,反正列都是动态的一般来说都没必要) elementTableColumn.prop = "completeShow" + taskItem.ID; elementTableColumns.Add(elementTableColumn); } List<ExpandoObject> expandoObjectList = new List<ExpandoObject>(); // 构建动态数据 foreach (VClassTeam item in vClassTeams) { //创建动态类型。表格这些需要动态显示 dynamic expandoObjectItem = new ExpandoObject(); // 转化成键值对方便动态赋值,这样给键值对赋值就会自动给expandoObjectItem赋值 var expandoDict = (IDictionary<string, object>)expandoObjectItem; // 固定列的数据 expandoDict["levelID"] = item.LevelID; expandoDict["gradeID"] = item.GradeID; expandoDict["classId"] = item.ID; expandoDict["className"] = item.ClassName; expandoDict["studentCount"] = studentClassList.Count(a => a.ClassID == item.ID); // 动态数据赋值 foreach (Tasks taskItem in tasks) { List<StuTaskDetail> stuTaskDetail_Item = stuTaskDetails.Where(a => a.ClassId == item.ID && a.TaskID == taskItem.ID).ToList(); // 给需要动态显示的列提供值(具体提供值的算法根据自己的业务逻辑来) expandoDict["completeShow" + taskItem.ID] = stuTaskDetail_Item.GroupBy(a => a.ClassId).Count() + "/" + stuTaskDetail_Item.Count(); } expandoObjectList.Add(expandoObjectItem); } ElementTableDynamic elementTableDynamic = new ElementTableDynamic(); elementTableDynamic.Columns = elementTableColumns; elementTableDynamic.Data = expandoObjectList; return elementTableDynamic; } ``` #### 接口返回的数据格式如下 ![](https://img.tnblog.net/arcimg/aojiancc2/8cb2f604d75f4731aa9948349fa1c60d.jpg) ## 前端需要复杂一些的模板解析 当数据不是简单的直接绑定一个列的时候,比如需要点击查询详情等,还需要提供详情的数据 比如前端需要这样绑定数据 ``` <el-table-column prop="managerOfficeMeetingCount" align="center" label="总经办会议" min-width="109"> <template #default="scope"> <span class="canclick" @click="showMonthDetails(scope.row.managerOfficeMeetingDetails, '总经办会议', scope.row.managerOfficeMeetingCount)">{{ scope.row.managerOfficeMeetingShow }}</span> </template> </el-table-column> ``` #### 后端 这样后端就还需要多提供几个数据,详情数据:managerOfficeMeetingDetails,条数:managerOfficeMeetingCount 等,后台大概的核心代码如下: ``` // 动态数据赋值 foreach (Tasks taskItem in tasks) { List<StuTaskDetail> stuTaskDetail_Item = stuTaskDetails.Where(a => a.ClassId == item.ID && a.TaskID == taskItem.ID).ToList(); // 给需要动态显示的列提供值(具体提供值的算法根据自己的业务逻辑来) expandoDict["completeShow" + taskItem.ID] = stuTaskDetail_Item.GroupBy(a => a.ClassId).Count() + "/" + stuTaskDetail_Item.Count(); expandoDict["completeCount" + taskItem.ID] = groupTasks_Item.GroupBy(a => a.ClassID).Count(); expandoDict["completeDetails" + taskItem.ID] = ProcGroupTasksDetails(item, schoolClassDtos, groupTasks_Item); } ``` 动态构建表头的时候就在加一个字段,方便前端解析的时候去取对应的数据 ``` // 构建动态的表头与属性对应的数据 List<ElementTableColumn> elementTableColumns = new List<ElementTableColumn>(); foreach (Tasks taskItem in tasks) { ElementTableColumn elementTableColumn = new ElementTableColumn(); elementTableColumn.label = taskItem.ReportName; elementTableColumn.prop = "completeShow" + taskItem.ID; // 多加一个字段,方便前端解析的时候去取 elementTableColumn.taskId = taskItem.ID+""; elementTableColumns.Add(elementTableColumn); } ``` ##### 这样修改后,后端返回的数据结构如下: 表头的数据结构: ![](https://img.tnblog.net/arcimg/aojiancc2/5f31fb162052485eb4c7a083735353a6.png) 具体数据的结构: ![](https://img.tnblog.net/arcimg/aojiancc2/b790d33321154cc0bc02a6fd8ffcdd2a.png) #### 前端 这种情况下详情数据前端解析的时候也要动态的来了,不能写死,要根据那个动态id来拼接出来取数据 ``` <!-- 循环出来需要动态显示的列 --> <el-table-column :label="item.label" min-width="139" align="center" :prop="item.prop" v-bind:key="index" v-for="(item, index) in state.dynamicColumns"> <template #default="scope"> <span class="canclick" @click="showMonthDetails(scope.row['completeDetails'+item.taskId], item.label,scope.row['completeCount'+item.taskId])">{{ scope.row[item.prop] }}</span> </template> </el-table-column> ``` ## 需要多级表头,合并表头的 效果如下: ![](https://img.tnblog.net/arcimg/aojiancc2/5595d1396fa5417c94d2d5d9032b2ba0.png) ##### element ui的多级表头格式如下,相当于就是有嵌套效果的 ``` <el-table-column label="地址"> <el-table-column prop="province" label="省份" width="120"> </el-table-column> <el-table-column prop="city" label="市区" width="120"> </el-table-column> </el-table-column> ``` ##### 后台表头的结构就需要变一下了,需要有一个子级 ``` public class ElementTableColumn { public string prop { get; set; } public string label { get; set; } public string taskId { get; set; } /// <summary> /// 可能有多级表头的情况 /// </summary> public List<ElementTableColumn> subTableColumn { get; set; } } ``` ##### 需要有子级的情况,后台构建的时候就要多添加一级 ``` // 构建动态的表头与属性对应的数据 List<ElementTableColumn> elementTableColumns = new List<ElementTableColumn>(); foreach (Tasks taskItem in tasks) { // 班级数量和具体的完成数量还要合并成一个单元来显示 ElementTableColumn elementTableColumnFather = new ElementTableColumn(); elementTableColumnFather.label = taskItem.ReportName; List<ElementTableColumn> subTableColumn = new List<ElementTableColumn>(); // 2024-5-29,说某个任务完成的班级数量单独作为一列显示出来,那么在加一列吧,放到那个显示的数据列前面 ElementTableColumn classCompleteCountTableColumn = new ElementTableColumn(); classCompleteCountTableColumn.label = "班级数"; classCompleteCountTableColumn.prop = "classCompleteCount" + taskItem.ID; classCompleteCountTableColumn.taskId = taskItem.ID + ""; subTableColumn.Add(classCompleteCountTableColumn); ElementTableColumn elementTableColumn = new ElementTableColumn(); elementTableColumn.label = "完成次数"; // 动态列名,用id来拼一个名称,显示的可能会随时调整 elementTableColumn.prop = "completeShow" + taskItem.ID; elementTableColumn.taskId = taskItem.ID + ""; subTableColumn.Add(elementTableColumn); elementTableColumnFather.subTableColumn = subTableColumn; elementTableColumns.Add(elementTableColumnFather); } ``` ##### 前台解析的时候多加一级循环即可 ``` <!-- 循环出来需要动态显示的列,需要合并一级的单元格 --> <el-table-column :label="fatheritem.label" align="center" v-for="(fatheritem, index) in state.dynamicColumns" :key="index"> <el-table-column :label="item.label" min-width="139" align="center" :prop="item.prop" v-bind:key="index" v-for="(item, index) in fatheritem.subTableColumn"> <template #default="scope"> <span class="canclick" @click="showMonthDetails(scope.row['completeDetails' + item.taskId], item.label, scope.row['completeCount' + item.taskId])">{{ scope.row[item.prop] }}</span> </template> </el-table-column> </el-table-column> ``` ##### 动态表头返回的数据结构的一部分如下 ![](https://img.tnblog.net/arcimg/aojiancc2/8b2006cc490b44daa11cb00ddf335e6d.png)
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739
👈{{preArticle.title}}
👉{{nextArticle.title}}
评价
{{titleitem}}
{{titleitem}}
{{item.content}}
{{titleitem}}
{{titleitem}}
{{item.content}}