遇到脑子有问题的产品经理该怎么办?如果有这么一个需求要你在一个可视区范围内不间断循环滚动几千上万条数据你会怎么去实现?
且不说提这个需求的人是不是脑子有问题,这个需求能不能实现?肯定是可以的,把数据请求回来渲染到页面写个滚动样式就好了。抛开这样一次性请求上万条数据合不合理不讲,一万条数据渲染到页面上估计都要卡死了吧。那有没有更好的方法呢? 当然有
分析一波思路
首先定义两个数组,一个滚动区域的数组scrollList,一个总数据的数组totalList,模拟一个异步请求的方法和获取数据的方法。
<script lang="ts" setup>
import { nextTick, ref } from "vue";
type cellType = {id: number,title: string,
}
interface faceRequest {data: cellType,total: number
}
// 总数据的数组
const totalList = ref<Array<cellType>>([]);
// 滚动的数组
const scrollList = ref<Array<cellType>>([]);
// 数据是否全部加载完毕
let loading: Boolean = false
// 模拟异步请求
const request = () => {return new Promise<faceRequest>((resolve: any, reject: any) => {let data: Array<cellType> = []// 每次返回30条数据for (let i = 0; i < 30; i++) {data.push({id: totalList.value.length + i,title: 'cell---' + (totalList.value.length + i)});}let total = 10000// 数据的总数resolve({ data, total })})
}
const getData = () => {request().then(res => {totalList.value = totalList.value.concat(res.data)// 默认获取第一次请求回来的数据if (totalList.value.length <= 30) {scrollList.value = scrollList.value.concat(res.data)}// 当前请求的数量小于总数则继续请求if (totalList.value.length < res.total) {getData()} else {loading = true}})
}
getData()
</script>
上面写好了数据的获取处理,接下来写一下页面
<template><div class="div"><div :style="styleObj" @mouseover="onMouseover" @mouseout="onMouseout" ref="divv"><div v-for="item in scrollList" :key="item.id" @click="onClick(item)"><div class="cell">{{ item.title }}</div></div></div></div>
</template>
<script lang="ts" setup> // 滚动样式
const styleObj = ref({transform: "translate(0px, 0px)",
}); </script>
<style scoped> .div {width: 500px;height: 500px;background-color: aquamarine;overflow: hidden;
}
.cell {height: 30px;
} </style>
现在页面跟数据的前提条件都写好,下面就是数据逻辑的处理了,也就是这篇文章的重点
1.获取页面上单条数据的总体高度
2.设置定时器使页面不停的滚动
3.当一条数据滚动出视图范围时调用处理数据的方法并且重置滚动高度为0
const divv = ref();
// 当前滚动高度
const ScrollHeight = ref<number>(0);
// 储存定时器
const setInt = ref();
// 内容滚动
const roll = () => {nextTick(() => {let offsetHeight = divv.value.childNodes[1].offsetHeightsetInt.value = setInterval(() => {if (ScrollHeight.value == offsetHeight) {onDel();ScrollHeight.value = 0;}ScrollHeight.value++;styleObj.value.transform = `translate(0px, -${ScrollHeight.value}px)`;}, 10);})
};
onMounted(() => {roll()
})
处理数据的方法
1.保存需要被删除的数据
2.删除超出视窗的数据
3.获取总数组的数据添加到滚动数组的最后一位
4.将被删除的数组数据添加到总数组最后面,
5.当滚动到最后一条数据时重置下标为0,使得数据首位相连不断循环
let index = 29;// 每次请求的数量-1,例如每次请求30条数据则为29
const onDel = () => {index++;if (loading) {// 当滚动到最后一条数据时重置下标为0if (index == totalList.value.length) {index = 0;}scrollList.value.shift();scrollList.value.push(totalList.value[index]);} else {if (index == totalList.value.length) {index = 0;}// 保存需要被删除的数据let value = scrollList.value[0]// 删除超出视窗的数据scrollList.value.shift();// 获取总数组的数据添加到滚动数组的最后一位scrollList.value.push(totalList.value[index]);// 将被删除的数组数据添加到总数组最后面totalList.value.push(value)}
};
到这里代码就写好了,接下来让我们看看效果怎么样
总结
在我们开发的过程中会遇到各种各样天马行空的需求,尤其会遇到很多不合理的需求,这时候我们就要三思而后行,
想清楚能不能不做?
能不能下次再做?
能不能让同事去做?
最后
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享