客户又要一次性滚动千万条数据...

欸,朋友们好,我是性能优化带师,寅时码

昨天,产品发来张截图,问我怎么这么卡

我一看,噢~原来是佐田,后端的数据,有三千多条,给我挤爆了

这时间,按照传统前端的方式,应该是 减数据、截数据、分段出

引言

像是什么 虚拟列表动态轮播图 之类的

我之前都做过了,也发过文章讲解

这次又需要做一个 动态加载的自动滚动组件


什么意思呢?

也就是仅仅加载看得见的数据,看不见的则不生成 DOM

当然,上面那句话只是最理想的状态,以目前浏览器提供的 API 来说

无缝滚动的动态加载都是障眼法,总会有一些多余的资源

回顾其他组件的实现方式

我之前做的 动态无缝轮播 组件,实际上是加载两份相同的资源实现

当需要切换时,用点障眼法就能实现

如果需要左右都能 无缝且动态 的轮播,那么就需要复制更多资源


我做的东西基本都是通用的(懒即动力 ),也就是说,只要你需要轮播、或者滚动

那么都可以使用,他会传递个插槽给你使用

动态无缝轮播图实现,含源码

直接放源码,我给你们省流,不会用的话看看文章末尾
gitee.com/cjl2385/dig...
gitee.com/cjl2385/dig...

看我这么体贴的份上,别光收藏,点点赞呀

实现动态加载数据滚动

这里就讲点技巧吧,我实现动态加载

只有两点

  1. 两份数据,一份隐藏
  2. 找准时机,偷偷摸摸的切换数据,让人看不出来

所以重点就是这个时机,你可以利用各种事件

在用户看不见的地方切换数据

这张图里,容器的大小实际上是红色的部分

接下来,我让他滚动起来,你们就能看到效果了

很简单对吧,一个循环的动画

那么下面我变直接隐藏右边,那么就实现了

怎么样,是不是毫无破绽

讲解

  1. 准备一个数组,让他的长度,设置为用户长度的两倍
  2. 容器设置溢出隐藏,所以这时能看见的,又变成了用户指定的大小
  3. 设置一个动画,动画执行仅仅到 50% 就够了
  4. 动画设置成无限循环
  5. 监听动画的某个事件,改变数组的数据

动画如下,我写的组件比较通用,所以方向也能设置

css 复制代码
@keyframes scrollX {
    100% {
        transform: translateX(-50%);
    }
}

@keyframes scrollY {
    100% {
        transform: translateY(-50%);
    }
}

上面说了要监听事件,那要监听什么事件呢?

显然是动画迭代完一次后的动画,每次迭代都会重新运行的事件

事件名我记得住吗?我记不住

那我是怎么写的呢?

靠猜

输入一点前缀,使用快捷键呼出代码提示,然后一个个看呗

我写的快捷键大全指南

这个叫 xxx Iterateiterate是不是很眼熟

没错,就是数组的迭代器,所以我猜就是他

那么怎么设置呢?

这里还是用老朋友,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>
相关推荐
武子康2 分钟前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
neter.asia12 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫13 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
passer__jw76730 分钟前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
十一吖i31 分钟前
前端将后端返回的文件下载到本地
vue.js·elementplus
光影少年32 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_33 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891135 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾37 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu39 分钟前
前端 Canvas 绘画 总结
前端