前端页面渲染多条数据长列表的性能优化

这篇具有很好参考价值的文章主要介绍了前端页面渲染多条数据长列表的性能优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

后端一次性返回了10w条数据,前端该如何处理?长列表性能优化
这个问题其实是考察面试者对性能优化的理解。我们知道,对于大量数据渲染的时候,JS运算并不是性能的瓶颈,性能的瓶颈主要在于渲染阶段,所以页面的卡顿是由于同时渲染大量DOM所引起的。

前端长数据渲染方案:

一、一次性渲染

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <ul id="container"></ul>

  <script>
    // 模拟十万条数据
    let total = 100000;
    // 直接渲染
    let ul = document.getElementById('container');
      const renderList = () => {
        for (let index = 0; index < total; index++) {
          const li = document.createElement("li");
          li.innerHTML = `${index}---${~~(Math.random()* total)}`;
          ul.appendChild(li);
        }
      };
      renderList()
  </script>
</body>
</html>

二、使用定时器进行分页渲染

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <ul id="container"></ul>

    <script>
      // 模拟十万条数据
      let total = 100000;
      let page = 0;
      // 每页插入limit条数据
      const limit = 200;
      //总页数
      const totalPage = Math.ceil(total / limit); // Math.ceil 1.1 => 2
      let ul = document.getElementById("container");

      //循环加载数据
      const renderList = (page) => {
        if (page >= totalPage) return;
        setTimeout(() => {
          for (let i = page * limit; i < page * limit + limit; i++) {
            const li = document.createElement("li");
            li.innerHTML = `${i}---${~~(Math.random() * total)}`;
            ul.appendChild(li);
          }
          renderList(page + 1);
        }, 0);
      };
      renderList(page);
    </script>
  </body>
</html>

简单聊一下 setTimeout 和闪屏现象
setTimeout的执行时间并不是确定的。在JS中, setTimeout任务被放进事件队列中,只有主线程执行完才会去检查事件队列中的任务是否需要执行,因此 setTimeout的实际执行时间可能会比其设定的时间晚一些。

刷新频率受屏幕分辨率和屏幕尺寸的影响,大多数电脑显示器的刷新频率是60Hz,大概相当于每秒钟重绘60次,因此不同设备的刷新频率可能会不同,而 setTimeout只能设置一个固定时间间隔,这个时间不一定和屏幕的刷新时间相同。

以上两种情况都会导致setTimeout的执行步调和屏幕的刷新步调不一致。

在 setTimeout中对dom进行操作,必须要等到屏幕下次绘制时才能更新到屏幕上,如果两者步调不一致,就可能导致中间某一帧的操作被跨越过去,而直接更新下一帧的元素,从而导致丢帧闪屏现象

三、使用 requestAnimationFrame

使用 requestAnimationFrame 代替 setTimeout,减少了重排的次数, requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机,极大提高了性能

如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是, requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象。

const renderList = (page) => {
        if (page >= totalPage) return;
        //使用 requestAnimationFrame 代替 setTimeout,减少重排次数
        requestAnimationFrame(() => {
          for (let i = page * limit; i < page * limit + limit; i++) {
            const li = document.createElement("li");
            li.innerHTML = `${i}---${~~(Math.random() * total)}`;
            ul.appendChild(li);
          }
          renderList(page + 1);
        });
      };
      renderList(page);

四、使用 DocumentFragment

先解释一下什么是 DocumentFragment

  1. DocumentFragments 是DOM节点。它们不是主DOM树的一部分。通常的用例是创建文档片段,将元素附加到文档片段,然后将文档片段附加到DOM树。
  2. 在DOM树中,文档片段被其所有的子元素所代替。因为文档片段存在于内存中,并不在DOM树中。
  3. 所以将子元素插入到文档片段时不会引起【页面回流】(对元素位置和几何上的计算)。

因此,使用文档片段通常会带来更好的性能。

const renderList = (page) => {
        if (page >= totalPage) return;
         requestAnimationFrame(() => {
          let fragment =  document.createDocumentFragment();
          for (let i = page * limit; i < page * limit + limit; i++) {
            const li = document.createElement("li");
            li.innerHTML = `${i}---${~~(Math.random() * total)}`;
            fragment.appendChild(li)
          }
          ul.appendChild(fragment)
          renderList(page + 1);
        });
      };
      renderList(page);

五、懒渲染/延迟渲染scrollTop、getBoundingClientRect

要获取用户的滚动位置,我们可以在列表末尾添加一个空节点空白。每当视口出现空白时,就意味着用户已经滚动到网页底部,这意味着我们需要继续渲染数据。

同时,我们可以使用getBoundingClientRect来判断空白是否在页面底部。

使用 Vue 的示例代码:

<script setup lang="ts">
import { onMounted, ref, computed } from 'vue'
const getList = () => {
  // code as before
}
const container = ref<HTMLElement>() // container element
const blank = ref<HTMLElement>() // blank element
const list = ref<any>([])
const page = ref(1)
const limit = 200
const maxPage = computed(() => Math.ceil(list.value.length / limit))
// List of real presentations
const showList = computed(() => list.value.slice(0, page.value * limit))
const handleScroll = () => {
  if (page.value > maxPage.value) return
  const clientHeight = container.value?.clientHeight
  const blankTop = blank.value?.getBoundingClientRect().top
  if (clientHeight === blankTop) {
    page.value++
  }
}
onMounted(async () => {
  const res = await getList()
  list.value = res
})
</script>

<template>
  <div id="container" @scroll="handleScroll" ref="container">
    <div class="sunshine" v-for="(item,index) in showList" :key="index">
      <span>{{ index }}</span>
      <img :src="item.src" />
    </div>
    <div ref="blank"></div>
  </div>
</template>

六、在vue里面:长列表性能优化

Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。文章来源地址https://www.toymoban.com/news/detail-642145.html

export default {  data: () => ({    users: {}  }),  async created() {    const users = await axios.get("/api/users");    this.users = Object.freeze(users);  }};

到了这里,关于前端页面渲染多条数据长列表的性能优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 已解决:Vue改变数据后界面不自动渲染,Vue中使用v-for遍历对象数组,当给其中某个元素对象重新赋值之后,页面组件列表没有渲染更新。

    问题如标题所说,Vue中使用v-for遍历对象数组,当给数组其中某个元素对象重新赋值之后,页面组件列表没有及时更新渲染,而是在页面进行了其他的渲染操作以后列表才更新出来新的数据,那同样给对象内的属性值赋值也可能存在不渲染的情况,一并解决,尤其发生在网络

    2024年02月06日
    浏览(50)
  • 前端性能优化之浏览器渲染优化

    在当今互联网高速发展的时代,用户对于网页加载速度和性能的要求越来越高。作为前端开发者,我们需要关注并致力于提升网页的加载和渲染性能,以提供更好的用户体验。而浏览器渲染优化正是我们实现这个目标的关键。在本文中,我们将探讨一些关于浏览器渲染优化的

    2024年02月11日
    浏览(31)
  • 理解React页面渲染原理,如何优化React性能?

    当使用React编写应用程序时,可以使用JSX语法来描述用户界面的结构。JSX是一种类似于HTML的语法,但实际上它是一种JavaScript的扩展,用于定义React元素。React元素描述了我们想要在界面上看到的内容和结构。 在运行React应用程序时,JSX会被转换成真实的DOM元素,这个过程主要

    2024年02月08日
    浏览(33)
  • 极致性能优化:前端SSR渲染利器Qwik.js

    前端性能已成为网站和应用成功的关键要素之一。用户期望快速加载的页面和流畅的交互,而前端框架的选择对于实现这些目标至关重要。然而,传统的前端框架在某些情况下可能面临性能挑战且存在技术壁垒。 在这个充满挑战的背景下,我们引入了 Qwik.js 框架。Qwik.js 不仅

    2024年02月05日
    浏览(52)
  • 【前端八股文】浏览器系列:性能优化——HTML、CSS、JS、渲染优化

    本系列目录:【前端八股文】目录总结 是以《代码随想录》八股文为主的笔记。详情参考在文末。 代码随想录的博客_CSDN博客-leecode题解,ACM题目讲解,代码随想录领域博主 性能优化,从以下几个方面来进行。 避免HTML中直接写CSS viewport加速页面渲染 使用语义化标签 减少标签的

    2023年04月20日
    浏览(52)
  • 前端页面性能优化指标

    优化用户体验的质量一直都是是每个Web站点长期成功的关键,网页核心的性能指标应该是随着时间的推移而不断演变的,目前谷歌浏览器公布的核心Web健康指标——Core Web Vitals包括加载体验、交互性和页面内容的视觉稳定性; 1. Largest Contentful Paint (LCP) : Web 页主要内容的加载

    2024年02月15日
    浏览(54)
  • 前端页面性能优化(完整归纳版)

    当优化前端页面性能时,可以从多个方面入手。以下是一些常见的优化技巧,使用 Markdown 格式展示: 压缩和合并文件 :减少请求次数,通过压缩和合并 CSS、JavaScript 文件来减小文件大小。 使用缓存 :通过设置适当的缓存头(Cache Headers)来利用浏览器缓存,减少重复加载资

    2024年02月12日
    浏览(33)
  • 极致性能优化:前端SSR渲染利器Qwik.js | 京东云技术团队

    前端性能已成为网站和应用成功的关键要素之一。用户期望快速加载的页面和流畅的交互,而前端框架的选择对于实现这些目标至关重要。然而,传统的前端框架在某些情况下可能面临性能挑战且存在技术壁垒。 在这个充满挑战的背景下,我们引入了 Qwik.js 框架。Qwik.js 不仅

    2024年02月05日
    浏览(35)
  • 前端页面性能优化,性能测试算法优化,MeterSphere开源持续测试平台v2.10.5 LTS版本发布

    2023年8月7日,MeterSphere一站式开源持续测试平台正式发布v2.10.5 LTS版本。自2023年5月发布v2.10 LTS版本后,MeterSphere开源项目组坚持每两周发布小版本,持续进行问题的修复更新,并针对部分功能进行优化。 本次发布的MeterSphere v2.10.5 LTS版本在前端页面性能、性能测试算法、后端

    2024年02月14日
    浏览(34)
  • 【 Vue3 性能优化】页面加载性能 与 更新性能

    Vue 在大多数常见场景下性能都是很优秀的,通常不需要手动优化。然而,总会有一些具有挑战性的场景需要进行针对性的微调。 数字化管理平台 Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus教程 权限系统-商城 个人博客地址 Web 性能优化主要有两个方面: 页面加载性能 首次访问时,应

    2024年02月14日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包