<!--
Name: 虚拟滚动实现
Date : 2022-11-15
-->
<template>
<div class="box" ref="boxRef" @scroll="scroll">
<div class="scroll-box" :style="{ height: scrollHeight }">
<div ref="itemRef" style="overflow:hidden;position: absolute;top:0;left:0;right:0" v-for="item, i in currArr"
:key="item" :style="{ transform: `translateY(${App.getPxtoRem((startIdx + i) * itemHeight)}rem)` }">
<div class="item">{{ item }}</div>
</div>
</div>
</div>
</template>
<script setup lang="ts" name="test">
import { nextTick, ref } from 'vue';
import { useAppStore } from './pinia/app';
const length = 5;
const App = useAppStore();
const arr = new Array(17).fill(1).map((e, i) => i + 1);
//
const boxRef = ref<HTMLDivElement>();
const itemRef = ref<HTMLDivElement[]>();
const itemHeight = ref(0);
// 默认滚动盒子高度与父盒子一样
const scrollHeight = ref('100%');
// 开始下标
const startIdx = ref(0);
// 结束下标
const endIdx = ref(length);
// 渲染的数据
const currArr = ref<any[]>();
// 当前滚动位置
const scrollTop = ref(0);
// 初始渲染
renderDom();
nextTick(() => {
// 获取单个内容高度
itemHeight.value = (itemRef.value && itemRef.value[0] as HTMLDivElement)?.clientHeight || 0;
// 获取内容总高度
scrollHeight.value = useAppStore().getPxtoRem(arr.length * itemHeight.value) + 'rem';
})
function scroll() {
// 获取滚动距离
scrollTop.value = boxRef.value?.scrollTop || 0;
// 计算当前偏移下标
let start = Math.floor(scrollTop.value / itemHeight.value) - 1;
// 如果不等于上一次滚动的偏移下标
if (startIdx.value != start) {
// 计算结束下标
let end = start + length;
// 如果开始下标小于0,就重置为0;
if (start < 0) start = 0;
// 如果结束下标大于内容末尾,重置为末尾一个
if (end > arr.length) end = arr.length;
startIdx.value = start;
endIdx.value = end;
renderDom();
}
}
function renderDom() {
// 截取渲染的数据内容
currArr.value = arr.slice(startIdx.value, endIdx.value)
}
</script>
<style lang="scss" scoped>
.box {
max-height: 600px;
overflow: hidden;
overflow-y: auto;
width: 375px;
margin: auto;
.scroll-box {
position: relative;
.item {
height: 200px;
margin-bottom: 10px;
background: #ccc;
}
}
}
</style>
虚拟滚动实现
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 要求: 实现一个angular多选下拉框组件,当有超过2000个选项时,滑动/挑选/全选均不卡。 正篇: 为了方便...