欸,朋友们好,我是性能优化带师,寅时码
昨天,产品发来张截图,问我怎么这么卡
我一看,噢~原来是佐田,后端的数据,有三千多条,给我挤爆了
这时间,按照传统前端的方式,应该是 减数据、截数据、分段出
引言
像是什么 虚拟列表 、动态轮播图 之类的
我之前都做过了,也发过文章讲解
这次又需要做一个 动态加载的自动滚动组件
什么意思呢?
也就是仅仅加载看得见的数据,看不见的则不生成 DOM
当然,上面那句话只是最理想的状态,以目前浏览器提供的 API 来说
无缝滚动的动态加载都是障眼法,总会有一些多余的资源
回顾其他组件的实现方式
我之前做的 动态无缝轮播 组件,实际上是加载两份相同的资源实现
当需要切换时,用点障眼法就能实现
如果需要左右都能 无缝且动态 的轮播,那么就需要复制更多资源
我做的东西基本都是通用的(懒即动力 ),也就是说,只要你需要轮播、或者滚动
那么都可以使用,他会传递个插槽给你使用
直接放源码,我给你们省流,不会用的话看看文章末尾
gitee.com/cjl2385/dig...
gitee.com/cjl2385/dig...
看我这么体贴的份上,别光收藏,点点赞呀
实现动态加载数据滚动
这里就讲点技巧吧,我实现动态加载
只有两点
- 两份数据,一份隐藏
- 找准时机,偷偷摸摸的切换数据,让人看不出来
所以重点就是这个时机,你可以利用各种事件
在用户看不见的地方切换数据
这张图里,容器的大小实际上是红色的部分
接下来,我让他滚动起来,你们就能看到效果了
很简单对吧,一个循环的动画
那么下面我变直接隐藏右边,那么就实现了
怎么样,是不是毫无破绽
讲解
- 准备一个数组,让他的长度,设置为用户长度的两倍
- 容器设置溢出隐藏,所以这时能看见的,又变成了用户指定的大小
- 设置一个动画,动画执行仅仅到 50% 就够了
- 动画设置成无限循环
- 监听动画的某个事件,改变数组的数据
动画如下,我写的组件比较通用,所以方向也能设置
css
@keyframes scrollX {
100% {
transform: translateX(-50%);
}
}
@keyframes scrollY {
100% {
transform: translateY(-50%);
}
}
上面说了要监听事件,那要监听什么事件呢?
显然是动画迭代完一次后的动画,每次迭代都会重新运行的事件
事件名我记得住吗?我记不住
那我是怎么写的呢?
靠猜
输入一点前缀,使用快捷键呼出代码提示,然后一个个看呗
这个叫 xxx Iterate
,iterate
是不是很眼熟
没错,就是数组的迭代器,所以我猜就是他
那么怎么设置呢?
这里还是用老朋友,vue 的响应式 API 实现
定义一个起始索引,一个结束索引
然后用计算属性,基于他们,算出最终的数组
以后仅仅需要修改索引,大大降低开发的心智负担,大爱响应式编程
这里的 showCount 就是展示的长度,上面说了要设置成两倍
此时,仅仅需要修改起始索引,即可完成
下面的函数,在动画迭代时运行即可
这样的话,就算有上千万条数据,也仅仅会展示容器大小 * 2 的长度
还有一些简单的细节,比如鼠标移入暂停动画什么的我就不讲了
源码里已经写了
源码使用说明
代码里我用到了一个设置大小的指令 v-resize
已经放在了仓库,大家在 main.ts
把指令加入即可,比如
ts
app.directive('resize', { ... }) // 或者使用 app.use,前提是要写成插件提供 install 方法
依赖
在文件里从 @jl-org/tool
里导入了一个函数,大家直接下载这个包即可
是我写的工具库,不想下载的话,去 npm
找,然后复制一下
www.npmjs.com/package/@jl...
代码示例
vue
<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>