移动端原生实现列表列固定横向滚动功能

news2024/12/23 5:55:43

功能介绍:

在移动端开发中,会用到列表作为信息展示方式,一般希望上下滚动时,可以固定表头,左右滚动时,可以固定最左列。

需求:

1、列表可以使用数组循环遍历;
2、上下滚动时,可以固定表头在最顶端显示;
3、左右滚动时,可以固定左边一列或多列可以固定显示;
4、列表的列宽允许在数组中设置;

思路:

1、页面使用四个dom元素分别存储四种元素:

1)固定在左上角,完全不参与滚动表头元素;
2)固定在顶部,只允许左右滚动表头元素;
3)固定在左侧,只允许上下滚动列元素;
4)右下角,左右上下均可随意滚动列元素;

2、表头数组与列表数据数组之间互相联系,表头属性可以控制列表列排序、列表宽度、是否为固定列等;

3、四个dom之间增加联动,使用@scroll、scrollLeft、scrollTop;

示意图:

列表固定滚动布局图

实现代码:

html代码:

<div class="table-box">
	<div class="listFlexSty">
		<div class="fixedHeadBox" :style="{width: fixedWid}">
			<div
				class="thClass"
				v-for="(item, index) in fixedHead"
				:key="index"
				:style="{width: item.width, justifyContent:item.name === '名称'?'flex-start':'',padding:item.name === '名称'?'0 10px':''}"
				@click="thItemClick(item)">
				<div>{{item.name}}</div>
				<div class="playIconSty">
					<div class="topArrow"></div>
					<div class="bottomArrow"></div>
				</div>
			</div>
		</div>
		<div
			class="nomalHeadBox"
			style="
				 {
					width: 'calc(100% - ' + fixedWid + ')';
				}
			">
			<div ref="nomalHeadBox" @scroll="scrollHList">
				<div class="thClass" :style="{width: nomalWid}">
					<div
						class="thClass"
						v-for="(item, index) in nomalHead"
						:key="index"
						:style="{width: item.width,padding:item.name === '折扣偏差'?'0 10px':''}"
						@click="thItemClick(item)">
						<div>{{item.name}}</div>
						<div class="playIconSty">
							<div class="topArrow"></div>
							<div class="bottomArrow"></div>
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div style="height: calc(100% - 40px); overflow: auto" id="dataBodyId">
		<div v-show="tBodyData.length!==0" class="listFlexSty">
			<div class="fixedListBox" :style="{width: fixedWid}">
				<div ref="fixedListBox" @scroll="scrollFList">
					<div class="rLineSty" v-for="(item, index) in tBodyData" :key="index">
						<div
							v-for="(it, inx) in fixedHead"
							:key="inx"
							:style="{width: it.width, justifyContent:it.name === '名称'?'flex-start':'',padding:it.name === '名称'?'0 10px':''}"
							class="thClass">
							<span v-if="it.prop === 'storeName' || it.prop === 'curDiscount'"
								>{{item[it.prop]}}</span
							>
							<span
								v-if="it.prop === 'orderAmount' || it.prop === 'diffAmount'"
								v-format="'#,##0.##'"
								>{{item[it.prop]}}</span
							>
							<span v-if="it.prop === 'completionRate'">{{item[it.prop]}}%</span>
							<span
								v-if="it.prop === 'yearEarlier'"
								:class="item[it.prop]<0?'downArrow':item[it.prop]>0?'upArrow':''"
								>{{item[it.prop]}}%</span
							>
							<span v-if="it.prop === 'diffDiscount'"
								>{{item[it.prop]>0?'+':''}}{{item[it.prop]}}</span
							>
						</div>
					</div>
				</div>
			</div>
			<div
				class="nomalListBox"
				ref="nomalListBox"
				:style="{width: 'calc(100% - '+fixedWid+')'}"
				@scroll="scrollList">
				<div
					class="rLineSty"
					:style="{width: nomalWid}"
					v-for="(item, index) in tBodyData"
					:key="index">
					<div
						v-for="(it, inx) in nomalHead"
						:key="inx"
						:style="{width: it.width,padding:it.name === '折扣偏差'?'0 10px':''}"
						class="thClass">
						<span v-if="it.prop === 'storeName' || it.prop === 'curDiscount'"
							>{{item[it.prop]}}</span
						>
						<span v-if="it.prop === 'orderAmount' || it.prop === 'diffAmount'" v-format="'#,##0.##'"
							>{{item[it.prop]}}</span
						>
						<span v-if="it.prop === 'completionRate'">{{item[it.prop]}}%</span>
						<span
							v-if="it.prop === 'yearEarlier'"
							:class="item[it.prop]<0?'downArrow':item[it.prop]>0?'upArrow':''"
							>{{item[it.prop]}}%</span
						>
						<span v-if="it.prop === 'diffDiscount'"
							>{{item[it.prop]>0?'+':''}}{{item[it.prop]}}</span
						>
					</div>
				</div>
			</div>
		</div>
		<div v-show="tBodyData.length>0 && !finished" class="bottomTip" @click="moreLoad">
			<span style="color: #999999">展开查看更多</span>
			<van-icon name="arrow-down" color="#999999" />
		</div>
		<div v-show="tBodyData.length>0 && finished" class="bottomTip">
			<span style="color: #999999">已加载完全部数据</span>
		</div>
		<div v-show="tBodyData.length===0" class="noData">暂无数据</div>
	</div>
</div>

js代码:

data(){
	return {
		// 下面是首页底部列表数据相关字段
		tHeadData: [
			{ name: '名称', prop: 'storeName', width: '100px', isfixed: true },
			{ name: '总业绩(元)', prop: 'orderAmount', width: '80px' },
			{ name: '平均折扣', prop: 'curDiscount', width: '80px' },
			{ name: '同比', prop: 'yearEarlier', width: '60px' },
			{ name: '完成率', prop: 'completionRate', width: '80px' },
			{ name: '缺口(元)', prop: 'diffAmount', width: '100px' },
			{ name: '折扣偏差', prop: 'diffDiscount', width: '80px' }
		],
		tBodyData: [],
		fixedHead: [],
		nomalHead: [],
		fixedWid: '',
		nomalWid: ''
	}
},

methods: {
	// 列表数据相关
	initData() {
		this.fixedHead = this.tHeadData.filter(item => {
			return item.isfixed;
		});
		this.nomalHead = this.tHeadData.filter(item => {
			return !item.isfixed;
		});
		this.initSize();
	},
	initSize() {
		let fwid = 0;
		let nwid = 0;
		this.fixedHead.forEach(item => {
			// 此处以px单位为例
			const len = item.width.length - 2;
			const width = item.width.substring(0, len) - 0;
			fwid += width;
		});
		this.nomalHead.forEach(item => {
			const len = item.width.length - 2;
			const width = item.width.substring(0, len) - 0;
			nwid += width;
		});
		this.fixedWid = fwid + 'px';
		this.nomalWid = nwid + 'px';
	},
	// 首页下方数据列表联动相关
	scrollHList() {
		this.$refs.nomalListBox.scrollLeft = this.$refs.nomalHeadBox.scrollLeft;
	},
	scrollFList() {
		this.$refs.nomalListBox.scrollTop = this.$refs.fixedListBox.scrollTop;
	},
	scrollList() {
		this.$refs.fixedListBox.scrollTop = this.$refs.nomalListBox.scrollTop;
		this.$refs.nomalHeadBox.scrollLeft = this.$refs.nomalListBox.scrollLeft;
	}
}


css代码:

.table-box {
	width: 100%;
	height: calc(100% - 80px);
	overflow: hidden;
}
.listFlexSty {
	display: flex;
}
.fixedHeadBox {
	height: 40px;
	line-height: 40px;
	color: #333333;
	font-size: 12px;
}
.nomalHeadBox {
	height: 40px;
	line-height: 40px;
	overflow: hidden;
	color: #333333;
	font-size: 12px;
}
.fixedListBox {
	height: 100%;
	overflow: hidden;
	color: #666666;
	font-size: 12px;
}
.nomalListBox {
	height: 100%;
	overflow: auto;
	color: #666666;
	font-size: 12px;
}
.thClass {
	display: flex;
	align-items: center;
	justify-content: flex-end;
}
.rLineSty {
	height: 34px;
	padding: 10px 0;
	display: flex;
}
.rLineSty > div {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	overflow: hidden;
}

/* 隐藏滚动条 */
/* 隐藏右边表格头部滚动条 */
.nomalHeadBox > div {
	overflow: auto;
	height: calc(100% + 10px);
}
/* 隐藏左边列表滚动条 */
.fixedListBox > div {
	overflow: auto;
	height: 100%;
	width: calc(100% + 10px);
}
.noDataNew {
	height: calc(100% - 40px);
	display: flex;
	align-items: center;
	justify-content: center;
	color: #999;
	font-size: 12px;
}

效果图:

列表固定滚动

注意: 代码里的方法thItemClick是列排序功能,与此文章无关,实现代码未贴出,除此之外,其他未贴出的代码均与此文章所讲功能无关,忽略即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1302011.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MISRA C++ 2023:C和C++测试解决方案实现静态分析

自动化软件测试解决方案的全球领导者Parasoft今天宣布&#xff0c;随着Parasoft C/Ctest 2023.2即将发布&#xff0c;全面支持MISRA C 2023。Parasoft针对C和C软件开发的完全集成测试解决方案计划于2023年12月发布&#xff0c;可以帮助团队实现自动化静态分析和编码标准合规性&…

Redis滚动分页的使用

Feed流 关注推送也叫Feed流。通过无限下拉刷新获取新的信息。 Feed流产品常见有两种模式&#xff1a; Timeline: 不做内容筛选&#xff0c;简单的按照内容发布时间排序&#xff0c;常用于好友或关注。例如朋友圈 优点&#xff1a;信息全面&#xff0c;不会有缺失。并且实现也…

JVM 运行时参数

面试题 JVM的参数&#xff0c;你知道的说一下 (百度) 说说你知道的几种主要的JVM参数&#xff08;京东&#xff09; JVM调优调的哪些参数&#xff1f;在哪里写这些参数&#xff1f; &#xff08;亚信&#xff09; 内存调优参数都有什么&#xff1f;&am…

【日常总结】root ssh第一天远程正常,次日无法访问,修正 PermitRootLogin yes 后 ,ssh root 还是不能访问

一、环境 二、场景 三、原因 四、解决方案 1. 客户设置账号过期时间 2. 修正 PermitRootLogin yes 后 &#xff0c;ssh root 还是不能访问 一、环境 客户项目&#xff1a;独立外网IP 服务器&#xff1a;Ubuntu 22.04.3 LTS ssh&#xff1a;外网映射到服务器22端口 二、…

我从来不理解JavaScript闭包,但我用了它好多年

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热衷分享有趣实用的文章&#xff0c;希望大家多多支持&#xff0c;一起进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 你是否学习了很久JavaScript但还没有搞懂闭包呢&#xff1f;今天就来聊一下…

精准捕捉异常时刻——从写好事件标题与内容开始

写在前面 在讨论如何写好监控器配置时的事件通知内容之前&#xff0c;需要明确这样一个逻辑&#xff1a; 当监控器检测规则生效后&#xff0c;它会针对系统业务数据进行一系列聚合数据处理并以事件的形式留存。这些事件记录可以理解为当前监控器检测对象发出的异常信号的承载…

WPS Office JS宏实现Excel转换为JSON格式数据

通过Excel JS宏&#xff0c;将表格中的数据以”列“形式导出为JSON数据格式。 我们在整理文档时&#xff0c;产品会通过Excel将功能点和功能描述分层级整理出来&#xff0c;有时需要将此数据导入到系统中&#xff0c;Web端对Json这类数据比较友好&#xff0c;所以这里试着使用E…

实现加盐加密方法以及MappedByteBuffer,RandomAccess

目录 自己实现 Spring Security MappedByteBuffer RandomAccess 加盐加密的实现 自己实现 传统MD5可通过彩虹表暴力破解&#xff0c; 加盐加密算法是一种常用的密码保护方法&#xff0c;它将一个随机字符串&#xff08;盐&#xff09;添加到原始密码中&#xff0c;然后再进…

Java面试题(每天10题)-------连载(46)

目录 Dubbo篇 1、Dubbo的默认集群容错方案 2、Dubbo支持哪些序列化方式&#xff1f; 3、Dubbo超时时间怎样设置&#xff1f; 4、服务调用超时问题怎么解决&#xff1f; 5、Dubbo在安全机制方面是如何解决的&#xff1f; 6、Dubbo和Dubbox之间的区别 7、Dubbo和Spring C…

java--正则表达式用于查找信息、用于搜索替换、分割内容

1.案例&#xff1a;使用正则表达式查找一段文本中的内容 需求&#xff1a;请把下面文本中的电话&#xff0c;邮箱&#xff0c;座机号码&#xff0c;热线都爬取出来。 2.正则表达式用于搜索替换、分割内容&#xff0c;需要结合String提供的如下方法完成

MySQL使用教程

数据构成了我们日益数字化的社会基础。想象一下&#xff0c;从移动应用和银行系统到搜索引擎&#xff0c;再到如 ChatGPT 这样的先进人工智能聊天机器人&#xff0c;这些工具若没有数据支撑&#xff0c;将寸步难行。你有没有好奇过这些海量数据都存放在哪里呢&#xff1f;答案正…

Java程序编写(下)

Scanner对象 通过java.util.Scanner来获得Scanner类 基本语法&#xff1a; Scanner s new Scanner(System.in)通过next()和nextLine()方法获取输入的字符串。 通过hasNext()和hasNextLine()判断是否还有输入的数据。 next(): 1、一定要读取到有效字符后才可以结束输入 2、…

uniapp移动端悬浮按钮(吸附边缘)

Uniapp移动端悬浮按钮可以通过CSS实现吸附边缘的效果。具体实现步骤如下&#xff1a; html&#xff1a; <movable-area class"movable-area"><movable-view class"movable-view" :position"position" :x"x" :y"y"…

列出最佳Aspera替代方案,给你执掌数据传输的权

Aspera是一种高速文件传输技术&#xff0c;广泛应用于科学研究、医疗保健、媒体和娱乐等领域。然而&#xff0c;由于Aspera的高昂价格&#xff0c;很多人不得不寻找替代方案。本文将列举最佳Aspera替代方案&#xff0c;以便执掌数据传输的权利。 1、FileZilla FileZilla是一款…

XUbuntu22.04之8款免费UML工具(一百九十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

基于ssm的电动车租赁网站论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本电动车租赁网站就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&…

FreeSSL申请免费域名证书

本文详细讲解如何申请免费证书&#xff0c;需要先准备好域名&#xff0c;将服务器IP和域名绑定。 1、注册FreeSSL账号 网址&#xff1a; https://freessl.org/ 2、申请流程 登录后首页输入域名&#xff0c;然后点击Create certificate&#xff0c;跳转到证书申请页面。 或者…

LLM中的Prompt提示

简介 在LLM中&#xff0c;prompt&#xff08;提示&#xff09;是一个预先设定的条件&#xff0c;它可以限制模型自由发散&#xff0c;而是围绕提示内容进行展开。输入中添加prompt&#xff0c;可以强制模型关注特定的信息&#xff0c;从而提高模型在特定任务上的表现。 结构 …

Ubuntu安装TensorRT

文章目录 1. 安装CUDAa. 下载CUDAb. 安装CUDAc. 验证CUDA 2. 安装CUDNNa. 下载CUDNNb. 安装CUDNNc. 验证CUDNN 3. 安装TensorRTa. 下载TensorRTb. 解压TensorRTc. 安装TensorRTd. 安装uff和graphsurgeone. 验证是否安装成功f. 备注 关注公众号&#xff1a;『AI学习星球』 回复&…

kafka支持外网访问

kafka支持外网访问 1.kafka正常部署之后如果不修改&#xff0c;外网是无法访问的&#xff0c;具体如下&#xff08;这里是单节点&#xff09; 2.这个时候需要修改kafka的config中的server.properties中的 listeners 修改为0.0.0.0 监控所有网卡&#xff0c;advertised.listene…