layui table处理奇葩后台数据实现复杂表头固定列功能

5 篇文章 0 订阅

        公司要求在手机上实现复杂表头表格,可以第一列固定,其他滑动的table功能,我看了下,在elementui中有这个功能,但是它的多级表头需要实现上下级的对象关系,而后台给我们返回的数据都是用colspan,rowspan渲染表头的,所以这个插件无法使用。

        然后退而求其实,使用比较简单的layui中的table,因为它的ui做的还可以。

layui table 的复杂多级表头是支持表头使用rowspan和colspan 的。

文档:https://www.layui.com/doc/modules/table.html

        但是要实现固定列功能,就必须让表头的filed关键字绑定数据的key,有些像jq table和bootstrap table,都是初始化表头,设置关键字,然后自动配上数据渲染table。

        我是要实现这样的表格(只是模板,每个表头配置的都不同),复杂表头,第一列固定:

        奇葩的是,后台在设计程序的时候,表头和数据是分开的,他的意思就是表头单独渲染,然后数据部分根据顺序写table就行了:

分别为: 数据,表头,表描述

 

数据就是普通的键值对数据;

表头就是按tr给的对象,每一行的内容文字,和对应的calspan,rowspan

表描述就是告你表的标题,和表格的数据顺序是按colModel的数据展示的

        虽然他安排的明明白白,按表头和表body分别渲染确实无问题,但是我要使用layui table实现复杂表头和列固定,表头就必须和数据key绑定,而表头给出的乱七八糟的colspan,rowspan以后的,处理起来很麻烦,要把它屡清楚很费脑细胞。

        开始靠前端处理数据:

        首先要搞清楚,colspan为1的一般都是需要绑定数据展示的,但数据中colspan为1的多行表头顺序并不能确定,所以无法按顺序为他们绑定key,此时,我想到了通过占位符,让每一行的总对象数都相同

        先看看原始数据:

//循环表头数据
				for(var i=0;i<headers.length;i++){
					var array=[];
					var header1=headers[i].colomnVos;
					//console.log(header1)
					//循环每列表头中的数据
					for(var j=0;j<header1.length;j++){
						var obj={}
						//此时只是构造对象的雏形,还不能绑定field
						obj={
							title:header1[j].name,
							rowspan:header1[j].rowspan,
							colspan:header1[j].colspan,
							style:{height:'auto'},
							align:'center',
							fake:false
						}
						array.push(obj)
						//关键:如果colspan不为1的话,就在它后面加几个占位对象
						if(header1[j].colspan!=1){
							var thisColspan=header1[j].colspan;
							for(var k=1;k<thisColspan;k++){
								obj={
									fake:true
								}
								array.push(obj)
							}
							
						}
					}
					tableCols.push(array);
				}
				//打印这个阶段的样子
				var fuzhi=JSON.stringify(tableCols);
				var fuzhi1=JSON.parse(fuzhi)
				console.log(fuzhi1)

再看看处理后的数据:

此时发现,已经插入了占位对象了,但是每一行的对象总数还是不一样,这是因为有的表头rowspan并以一定为1

        比如地市这一列直接跨了3行,那下面的即使把rowspan全部展开添加占位对象也会少一个对象,所以除了rowspan,还需要考虑colspan的问题。

        现在可以确定的第一行的表头不管怎样,不需要考虑rowspan,将colspan全部展开必定代表表格的最大列数,那么我可以以最大列数开始纵向循环,如果上一级表头rowspan不是1,则在下面rowspan级表头这个位置也插入一个占位对象,描述很难,直接上代码:

//从第一个开始纵向循环,maxHeaderLength是表数据中获取的最大列数
				for(var i=0;i<maxHeaderLength;i++){
					for(var j=0;j<tableCols.length;j++){
						var header1=tableCols[j];
						if(!!header1[i]){
							//此时,可以判断colspan为1的都有自己的数据,为其绑定field
							if(header1[i].colspan==1){
								if(i==0){
									header1[i].field=pageConfVo[i];
									header1[i].fixed='left'
								}else{
									header1[i].field=pageConfVo[i];
								}
							}
							//关键:如果rowspan不为1,就在下面的表头中分别插入一个占位对象
							if(header1[i].rowspan>1){
								for(var k=0;k<header1[i].rowspan-1;k++){
									tableCols[j+k+1].splice(i, 0, {fake:true});
								}
							}
						}
					}
				}
				var aaa=JSON.stringify(tableCols)
				console.log(JSON.parse(aaa))

这时,再看下数据:

这就大功告成啦,可以保证每一行表头中,colspan为1所对应的列都是唯一的,所以就可以直接给他们赋值field的了。

        赋值好后当然要把没用的占位对象删掉:

//最后
				for(var i=0;i<tableCols.length;i++){
					var header2=tableCols[i];
					
					for(var j=0;j<header2.length;j++){
						if(header2[j].fake){
							header2.splice(j--,1);
						}
					}
				}
				console.log(tableCols)

最后的结果:

又回到了原始状态,但是不同的是该绑定数据key的列都绑定上了。

很不容易呀,下来粘下完整代码:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Layui</title>
  <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link rel="stylesheet" href="../lib/layui/css/layui.css"  media="all">
  <script src="../js/ipAddress.js" type="text/javascript" charset="utf-8"></script>
  <!-- 注意:如果你直接复制所有代码到本地,上述css路径需要改成你本地的 -->
  <style type="text/css">
  	#title{
		font-size:16px;
		font-weight:bold;
		text-align: center;
		line-height: 30px;
		padding:10px
	}
	.layui-table-header{
		
	}
	.shuoming{
		line-height: 26px;
		background: #E8F4FF;
		border-bottom:1px solid #ddd;
		padding:10px;
		font-size:13px
	}
	.shuoming .s1{
		color:white;
		background:#439FFF;
		display: inline-block;
		padding:0 10px;
		border-radius: 10px;
		margin-right:10px;
	}
	thead .layui-table-cell{
		height:40px !important;
		white-space:normal;
		padding:0;
	}
	.span{
		
	}
	.tip{
		line-height:60px;
		color:#aaa;
		font-size:16px;
		text-align: center;
		display: none;
	}
  </style>
</head>
<body>
	<div class="shuoming">
		<span class="s1">指标说明</span>
		<span>指标口径请参阅市场部崔炎下发的指标说明,对指标有疑问或建议,请联系市场部崔炎或业支部陈哲。</span>
	</div>
	<div id="title">
		
	</div>
	<table id="demo" lay-filter="test"></table>
	<div class="tip">
		暂无数据
	</div>
               
<script src="../js/jquery-3.3.1.min.js" type="text/javascript" charset="utf-8"></script>          
<script src="../lib/layui/layui.js" charset="utf-8"></script>
<!-- 注意:如果你直接复制所有代码到本地,上述 JS 路径需要改成你本地的 -->
<script>
	var table
    var tableCols=[];
	var height=0;
	var qryDate="";
	var sign="";
	var areaCode="";
	var tableCode="";
	var type="";
	//表的裂数
	var maxHeaderLength=0;
	//表头文字长度
	var maxTextLength=0;
	//var url=baseUrl+'tongbao/getTongBaoDataJson.action';
	var url='../static/data.json';
	
	$(function(){
		var args=getQueryStringArgs();
		qryDate=args.qryDate;
		sign=args.sign;
		areaCode=args.areaCode;
		tableCode=args.tableCode;
		type=args.type;
		
		$.ajax({
			type: 'get',
			url: url,
			data:{
				qryDate:qryDate,
				sign:sign,
				areaCode:areaCode,
				tableCode:tableCode,
				type:type
			},
			dataType: 'json',
			async:false,
			success: function(res){
				console.log(res)
				if(res.data.length==0){
					$(".tip").show();
				}
				var data =res.data[0];
				var headers=data.headThVos;
				var pageConfVo= data.pageConfVo.colModels;
				maxHeaderLength=parseInt(data.pageConfVo.colCount);
				$("#title").html(data.pageConfVo.cTitle)
				
				//循环表头数据
				for(var i=0;i<headers.length;i++){
					var array=[];
					var header1=headers[i].colomnVos;
					//console.log(header1)
					//循环每列表头中的数据
					for(var j=0;j<header1.length;j++){
						var obj={}
						if(header1[j].name.length>maxTextLength){
							maxTextLength=header1[j].name.length;
						}
						//此时只是构造对象的雏形,还不能绑定field
						obj={
							title:header1[j].name,
							rowspan:header1[j].rowspan,
							colspan:header1[j].colspan,
							style:{height:'auto'},
							align:'center',
							fake:false
						}
						array.push(obj)
						//关键:如果colspan不为1的话,就在它后面加几个占位对象
						if(header1[j].colspan!=1){
							var thisColspan=header1[j].colspan;
							for(var k=1;k<thisColspan;k++){
								obj={
									fake:true
								}
								array.push(obj)
							}
							
						}
					}
					tableCols.push(array);
				}
				//打印这个阶段的样子
				var fuzhi=JSON.stringify(tableCols);
				var fuzhi1=JSON.parse(fuzhi)
				console.log(fuzhi1)
				//从第一个开始纵向循环,maxHeaderLength是表数据中获取的最大列数
				for(var i=0;i<maxHeaderLength;i++){
					for(var j=0;j<tableCols.length;j++){
						var header1=tableCols[j];
						if(!!header1[i]){
							//此时,可以判断colspan为1的都有自己的数据,为其绑定field
							if(header1[i].colspan==1){
								if(i==0){
									header1[i].field=pageConfVo[i];
									header1[i].fixed='left'
								}else{
									header1[i].field=pageConfVo[i];
								}
							}
							//关键:如果rowspan不为1,就在下面的表头中分别插入一个占位对象
							if(header1[i].rowspan>1){
								for(var k=0;k<header1[i].rowspan-1;k++){
									tableCols[j+k+1].splice(i, 0, {fake:true});
								}
							}
						}
					}
				}
				var aaa=JSON.stringify(tableCols)
				console.log(JSON.parse(aaa))
				//最后
				for(var i=0;i<tableCols.length;i++){
					var header2=tableCols[i];
					
					for(var j=0;j<header2.length;j++){
						if(header2[j].fake){
							header2.splice(j--,1);
						}
					}
				}
				console.log(tableCols)
			},
			error:function(data) {
				//console.log(data.msg);
			},
		});	
	})
	
	layui.use('table', function(){
	  table = layui.table;
	  //console.log(height)
	  //第一个实例
	  table.render({
		  id:"itest",
		  where: {
				qryDate:qryDate,
				sign:sign,
				areaCode:areaCode,
				tableCode:tableCode,
				type:type
			},
		elem: '#demo',
		size: 'sm',
		//,height: height
		url: url ,//数据接口
		parseData: function(res){ //res 即为原始返回的数据
			//console.log(res)
			var data=res.data[0];
			var count=data.contents.length;
			var data1=data.contents;
			//console.log(height)
			
		    return {
		      "code": res.code, //解析接口状态
		      "msg": res.msg, //解析提示文本
		      "count": count, //解析数据长度
		      "data": data1 //解析数据列表
		    };
		},
		page: false, //开启分页
		cols: tableCols,
		cellMinWidth:100,
		done: function(res, curr, count){
		    //如果是异步请求数据方式,res即为你接口返回的信息。
		    //如果是直接赋值的方式,res即为:{data: [], count: 99} data为当前页数据、count为数据总长度
		    console.log(res);
		    
		    //得到当前页码
		    console.log(curr); 
		    
		    //得到数据总量
		    console.log(count);
			
			console.log(maxTextLength)
			if(maxTextLength>16){
				$("thead .layui-table-cell").css("fontSize",'10px')
			}
		  },
		  error:function(){
			  
		  }
	  });
	  
	});
	
	
	/* window.onresize = () => {
	  return (() => {
		 if(document.documentElement.clientHeight>document.documentElement.clientWidth){
			  that.titleHeight=50;
		  }else{
			  that.titleHeight=40;
		  }
		window.screenHeight = document.documentElement.clientHeight
		height = window.screenHeight-250;
		//console.log(window.screenHeight)
		//console.log(height)
		//table.resize('itest');
		table.reload('itest', {}, false)
	  })() 
	}*/
	
	function getQueryStringArgs() {
		//取得查询字符串并去掉开头的问号
		var qs = (location.search.length > 0 ? location.search.substring(1) : ""),
	
			//保存数据的对象
			args = {},
	
			//取得每一项
			items = qs.length ? qs.split("&") : [],
			item = null,
			name = null,
			value = null,
			//在 for 循环中使用
			i = 0,
			len = items.length;
		//逐个将每一项添加到 args 对象中
		for(i = 0; i < len; i++) {
			item = items[i].split("=");
				name = decodeURIComponent(item[0]);
				value = decodeURIComponent(item[1]);
				if(name.length) {
					args[name] = value;
				}
			}
		
			return args;
	}
</script>

</body>
</html>

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
可以通过使用CSS的position属性和JavaScript实现layui table表头和第一固定,其他可以滚动的效果。具体实现步骤如下: 1. 首先,在layui table中,需要在HTML中添加一个div元素,用来包裹表格。例如: ```html <div class="table-wrapper"> <table class="layui-table"> <!-- 表格内容 --> </table> </div> ``` 2. 在CSS中,需要对表格进行样式设置,包括表格的宽度、高度和边框等样式,同时需要设置表头和第一的position属性为fixed,以实现固定效果。例如: ```css .table-wrapper { width: 100%; height: 500px; overflow: auto; position: relative; } .layui-table thead tr { position: fixed; top: 0; z-index: 1; } .layui-table tbody td:first-child { position: sticky; left: 0; } ``` 3. 在JavaScript中,需要实现滚动事件,当表格内容滚动时,将表头和第一的位置进行调整,以保持固定效果。例如: ```javascript var wrapper = document.querySelector('.table-wrapper'); var table = document.querySelector('.layui-table'); var thead = table.querySelector('thead tr'); var tbody = table.querySelector('tbody'); var firstColumn = tbody.querySelector('td:first-child'); wrapper.addEventListener('scroll', function() { thead.style.transform = 'translateY(' + this.scrollTop + 'px)'; firstColumn.style.transform = 'translateX(' + this.scrollLeft + 'px)'; }); ``` 通过以上步骤,即可实现layui table表头和第一固定,其他可以滚动的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆趣编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值