客户又要一次性滚动千万条数据...
欸,朋友们好,我是性能优化带师,寅时码 昨天,产品发来张截图,问我怎么这么卡 我一看,噢~原来是佐田,后端的数据,有三千多条,给我挤爆了 这时间,按照传统前端的方式,应该是 减数据、截数据、分段出
引言
像是什么 虚拟列表、动态轮播图 之类的 我之前都做过了,也发过文章讲解
这次又需要做一个 动态加载的自动滚动组件
什么意思呢?
也就是仅仅加载看得见的数据,看不见的则不生成 DOM 当然,上面那句话只是最理想的状态,以目前浏览器提供的 API 来说 无缝滚动的动态加载都是障眼法,总会有一些多余的资源
回顾其他组件的实现方式
我之前做的 动态无缝轮播 组件,实际上是加载两份相同的资源实现 当需要切换时,用点障眼法就能实现 如果需要左右都能 无缝且动态 的轮播,那么就需要复制更多资源
我做的东西基本都是通用的(懒即动力),也就是说,只要你需要轮播、或者滚动 那么都可以使用,他会传递个插槽给你使用
直接放源码,我给你们省流,不会用的话看看文章末尾 gitee.com/cjl2385/dig… gitee.com/cjl2385/dig…
看我这么体贴的份上,别光收藏,点点赞呀
实现动态加载数据滚动
这里就讲点技巧吧,我实现动态加载 只有两点
- 两份数据,一份隐藏
- 找准时机,偷偷摸摸的切换数据,让人看不出来
所以重点就是这个时机,你可以利用各种事件 在用户看不见的地方切换数据
这张图里,容器的大小实际上是红色的部分 接下来,我让他滚动起来,你们就能看到效果了

很简单对吧,一个循环的动画 那么下面我变直接隐藏右边,那么就实现了

怎么样,是不是毫无破绽
讲解
- 准备一个数组,让他的长度,设置为用户长度的两倍
- 容器设置溢出隐藏,所以这时能看见的,又变成了用户指定的大小
- 设置一个动画,动画执行仅仅到 50% 就够了
- 动画设置成无限循环
- 监听动画的某个事件,改变数组的数据
动画如下,我写的组件比较通用,所以方向也能设置
@keyframes scrollX {
100% {
transform: translateX(-50%);
}
}
@keyframes scrollY {
100% {
transform: translateY(-50%);
}
}
上面说了要监听事件,那要监听什么事件呢? 显然是动画迭代完一次后的动画,每次迭代都会重新运行的事件
事件名我记得住吗?我记不住 那我是怎么写的呢?
靠猜
输入一点前缀,使用快捷键呼出代码提示,然后一个个看呗
这个叫 xxx Iterate
,iterate
是不是很眼熟
没错,就是数组的迭代器,所以我猜就是他

那么怎么设置呢? 这里还是用老朋友,vue 的响应式 API 实现
定义一个起始索引,一个结束索引 然后用计算属性,基于他们,算出最终的数组 以后仅仅需要修改索引,大大降低开发的心智负担,大爱响应式编程
这里的 showCount 就是展示的长度,上面说了要设置成两倍

此时,仅仅需要修改起始索引,即可完成 下面的函数,在动画迭代时运行即可
这样的话,就算有上千万条数据,也仅仅会展示容器大小 * 2 的长度
还有一些简单的细节,比如鼠标移入暂停动画什么的我就不讲了 源码里已经写了
源码使用说明
代码里我用到了一个设置大小的指令 v-resize
已经放在了仓库,大家在 main.ts
把指令加入即可,比如
app.directive('resize', { ... }) // 或者使用 app.use,前提是要写成插件提供 install 方法
依赖
在文件里从 @jl-org/tool
里导入了一个函数,大家直接下载这个包即可
是我写的工具库,不想下载的话,去 npm
找,然后复制一下
www.npmjs.com/package/@jl…
代码示例
<VirtualScroll :data="data"
style="width: 400px;"
:speed="120"
:item-size="100">
<template v-slot="{ item }">
<div class="item">{{ item.data }}</div>
</template>
</VirtualScroll>
<script setup lang="ts">
const data = ref(Array.from({ length: 99999 }, (_, i) => ({ data: i + 1 })))
</script>
<style>
.item {
font-size: 30px;
background-color: lightblue;
border: 1px solid;
height: 100%;
width: 100%;
}
</style>
转载自:https://juejin.cn/post/7360892717545521161