Kros的博客 Kros的博客
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云

Kros

凡心所向,素履以往,生如逆旅,一苇以航
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云
  • CSS

  • JavaScript

  • 工具

  • Vue

    • vue批量引入组件
    • vue中watch用法
    • vue使用基础JSX语法
    • vue首页白屏
    • vue长列表优化
    • 模板文件中script、template、style存在必要性
    • popup弹窗组件
    • 使用$mount和extend扩展vue
    • 扩展toast合并popup(按需加载)
    • canvas实现弧形进度条
    • vue中使用CSS Modules
    • vue实现无限轮播图
    • vue半圆形菜单
    • 纯CSS实现圆形进度条
    • v-model简单实现
    • vue带箭头下拉框
    • vue事件修饰符
    • vue鼠标悬浮显示提示文字
    • vue添加发布版本号方法
    • vue配置全局样式文件
    • vue在env development中设置全局变量不生效
    • vue引入less或scss全局变量
    • vue中使用Keepalive
    • vue2为什么只支持一个根节点
    • vue打包优化分析工具—webpack-bundle-analyzer
    • vue使用echarts(按需加载)
    • echarts柱形图重合堆叠
    • vue使用draggable实现多列拖拽(解决空列不能拖拽问题)
    • vue禁止三方库打包到bundle中
    • npm run serve运行背后的思考
    • vxe-table树结构不允许insert
    • vue组件延迟加载
    • 多页面应用配置
    • vue项目常用优化
    • vue实现拖动拼图验证码
    • vue虚拟dom
    • canvas心形动画
    • canvas绘制玫瑰曲线
    • element表单validateField验证部分字段
    • element日期选择限制今天以后并精确到小时
    • 前端使用JSEncrypt和node-rsa进行rsa加密传输和接收解密
    • elementui日期选择器生日只选择月和日不选择年并隐藏年份
    • el-upload组件第二次点击手动submit时不生效
    • element表单内输入框使用@keyup enter native回车时会刷新页面
  • antdv踩坑记录

  • Vue3

  • 前端
  • Vue
kros
2020-12-03

vue长列表优化

思路: 先指定显示内容区域高度,初始的滚动列表数据高度要比内容区域要高。以向上滚动为例,检测到滚动列表靠近底部时进行一下几个操作:向底部添加x个元素;删除顶部x个元素;向上滚动x个元素高度。向上滚动的目的是抵消头部删除的x个元素产生的滚动位置偏差

1 2

直接上代码

<template>
	<div class="content">
		<div class="list-box" id="listBox" @scroll="scrollI">
			<div class="list-body" id="listBody">
				<div class="item"v-for="(item, index) in cList" :key="index">{{item}}</div>
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		data() {
			return {
				list: [],  // 所有列表数据
				cList: [], // 滚动列表
				start: 0,  
				num: 100, // 滚定显示数量
				step: 10  // 滚动替换数量
			}
		},
		created() {
			for(let i = 0; i < 1000; i++) this.list.push(i);
			// 初始显示的内容截取列表num个
			this.cList = this.list.slice(this.start, this.start + this.num);
		},
		mounted() {			
			this.listBox = document.getElementById("listBox");
			this.listBody = document.getElementById("listBody");
			this.scrollTimer = null;
			// 滚动方向,1向上;2向下
			this.dir = 1;
			this.scrollTop = 0;
			// 可滚动的高度为:内容高度 - 可视区域高度,即滚动条的最大距离
			this.scrollHeight = this.listBody.offsetHeight - this.listBox.offsetHeight;
		},
		methods: {
			scrollI(e) {
				let top = this.listBox.scrollTop
				this.dir = top > this.scrollTop ? 1 : -1;
				// 节流
				if(!this.scrollTimer) {
					// 向上滚动
					if(this.dir > 0 && this.scrollHeight - top < 100) {
						// 这里可以触发上拉
						if(this.start + this.num == this.length) return;
						
						this.scrollTimer = setTimeout(() => {		
							// 数据是否填充完
							let sStep = (this.start + this.step + this.num > this.list.length) ? (this.list.length - this.start - this.num - 1 ) : this.step;
							// 移动clist在list中的位置
							this.start += this.step;							
							// 截取指定数量数据,相当于头部删除尾部添加
							this.cList = this.list.slice(this.start, this.start + this.num);
							// 将滚动位置偏移sStep个元素
							this.listBox.scrollTo({
								top: top - this.scrollHeight * (sStep / this.num) ,
								behavior: 'auto'
							})
							this.scrollTimer = null;
						}, 100);
					}else if(this.dir < 0 && top < 100) {
						// 向下滚动
						
						// 这里可以触发下拉
						if(this.start == 0) return;
						
						this.scrollTimer = setTimeout(() => {
							let cStep = this.start - cStep < 0 ? this.start : this.step;
							this.start -= cStep;								
							this.cList = this.list.slice(this.start, this.start + this.num);
							this.listBox.scrollTo({
								top: top + this.scrollHeight * (cStep / this.num) ,
								behavior: 'auto'
							})
							this.scrollTimer = null;
						}, 100);
					}
				}
			}
		}
	}
</script>

<style scoped>
	.content {
		/* width: 100vw;
		height: 100vh; */
	}
	.list-box {
		position: relative;
		width: 400px;
		height: 300px;
		overflow-x: hidden;
		overflow-y: scrill;
	}
	.list-body {
		position: absolute;
		top: 0;
		min-height: 10px;
		height: auto;
		margin: 0 auto;
		width: 400px;
		height: auto;
		
	}
	.list-box::-webkit-scrollbar {
	  display: none;
	}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#vue
上次更新: 2025/09/05, 8:09:00
vue首页白屏
模板文件中script、template、style存在必要性

← vue首页白屏 模板文件中script、template、style存在必要性→

最近更新
01
Find the next perfect square
09-05
02
Regex validate PIN code
09-05
03
Find the odd int
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 kros king
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
icon-heart-o icon-heart icon-infinity icon-pause icon-play link next prev