分段渲染加载页面

前言

在日常工作中我们一定会遇到某个页面需要渲染比较多的内容,比如列表或者文字;一般当数据过多的时候,就会出现页面加载比较慢,很长时间没有内容的展示,用户体验不太好,当然这时候就有人会说直接使用虚拟滚动嘛,只展示其中一部分数据。这种确实是一个非常好的办法,但是如果页面可能不能使用虚拟滚动实现呢(虽然少,但是有可能),此时我们就需要实现分段渲染

一、分段渲染是什么?

分段渲染就是每次只渲染一部分数据,比如我有1w条数据,我每次只渲染其中10条或者20条数据。

二、实现

1.不使用分段渲染

首先我们先看一下不使用分段渲染,直接渲染全部数据是什么样子的,我们先降低浏览器的CPU,模拟低配置的运行方式

这里我们使用推荐的

javascript 复制代码
<template>
  <div>
    <ul>
      <li v-for="item in total" :key="item.id" style="margin-top: 10px">
        <div>显示其他内容</div>
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const observer = new PerformanceObserver((list) => {
  console.log(list);
  const entries = list.getEntriesByName("first-paint");
  if (entries.length > 0) {
    const fcpTime = entries[0].startTime;
    console.log("First Contentful Paint:", fcpTime, "ms");
    observer.disconnect(); // 获取到数据后断开观察器
  }
});

observer.observe({ type: "paint", buffered: true });
const total = ref([]);
// 造1000条数据
const startTime = performance.now();
for (let i = 0; i < 10000; i++) {
  total.value.push({
    id: i,
    name: `name${i}`,
    age: 18 + i,
  });
}
const endTime = performance.now();
console.log(`数据生成,耗时:${endTime - startTime}ms`);


我们能看到,FCP的时间高达1000+ms,每次刷新有偏差,但是基本都是1000+的

2 使用分段渲染

javascript 复制代码
<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item.id" style="margin-top: 10px">
        <div>显示其他内容</div>
        {{ item.name }}
      </li>
    </ul>
  </div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const observer = new PerformanceObserver((list) => {
  const entries = list.getEntriesByName("first-paint");
  if (entries.length > 0) {
    const fcpTime = entries[0].startTime;
    console.log("First Contentful Paint:", fcpTime, "ms");
    observer.disconnect(); // 获取到数据后断开观察器
  }
});

observer.observe({ type: "paint", buffered: true });
const total = ref([]);
// 造1000条数据
const startTime = performance.now();
for (let i = 0; i < 10000; i++) {
  total.value.push({
    id: i,
    name: `name${i}`,
    age: 18 + i,
  });
}
const endTime = performance.now();
console.log(`数据生成,耗时:${endTime - startTime}ms`);
const list = ref([]);
// 使用requestAnimationFrame分批次渲染
const renderBatch = () => {
  const batchSize = 100;
  const totalItems = total.value.length;
  let startIndex = 0;
  const renderNextBatch = () => {
    const endIndex = startIndex + batchSize;
    const batchItems = total.value.slice(startIndex, endIndex);

    list.value.push(...batchItems);
    startIndex = endIndex;

    if (startIndex < totalItems) {
      requestAnimationFrame(renderNextBatch);
    }
  };
  renderNextBatch();
};
renderBatch();

这里使用requestAnimationFrame进行渲染,如果不清楚的可自行查阅mdn文档

此时我们看看结果


此时结果最大1088ms,也能看出来提升较为明显;

不过会出现滚动条会一直变小,因为不断在渲染加载新的数据,当然这也不算什么大问题;

当然也不一定非得用requestAnimationFrame,用延时器也是一样的,目的都是为了每次只加载一部分数据

总结

以上就是关于通过使用分段渲染来达到快速加载数据的方法,当然,这种方式并不是最好的,因为真正涉及到大数据列表还是虚拟滚动的性能和效果最好。

相关推荐
光电的一只菜鸡8 小时前
高通tuning中eis需要调什么
java·开发语言·前端
quweiie8 小时前
腾讯云视频点播-web上传视频
前端·音视频·腾讯云·上传视频·腾讯云视频点播
API快乐传递者8 小时前
1688 跨境电商 API 接口实战指南:从寻源到代采的全链路技术方案
java·前端·数据库
马可家的菠萝8 小时前
收藏不是终点:一个真正有用的个人知识库,至少要完成“收集 → 理解 → 行动”
前端·后端·架构
明月_清风9 小时前
看完 DSH 文档后,我总结了这 7 个关键点
前端·后端·deepseek
qq_452396239 小时前
第八篇:《Monorepo 实战:Turborepo 与 pnpm workspace 驱动的大型项目协作》
前端
数据狐(Datafox)9 小时前
1688.item_search工程实战:1688商品列表API分页采集与B2B货源数据分析落地
java·前端·数据分析
铁皮饭盒9 小时前
浏览器AI肯定离不开onnxruntime, 微软开源
前端·javascript·后端
vivo互联网技术9 小时前
vivo 广告小游戏:从"写代码"到"说需求"
前端·人工智能·游戏开发