您现在的位置是:首页 > 技术教程 正文

前端如何优化大量数据处理

admin 阅读: 2024-04-01
后台-插件-广告管理-内容页头部广告(手机)

一、从数据上处理:

分页分表,比如前端可以把数据分页展示,后端也分段吐数据

对数据进行分页。假设每个页面都有limit记录,那么数据可以分为Math.ceil(total/limit)个页面。之后,我们可以使用 setTimeout 顺序渲染页面,一次只渲染一个页面。

  1. const renderList = async () => {
  2. const list = await getList()
  3. const total = list.length
  4. const page = 0
  5. const limit = 200
  6. const totalPage = Math.ceil(total / limit)
  7. const render = (page) => {
  8. if (page >= totalPage) return
  9. setTimeout(() => {
  10. for (let i = page * limit; i < page * limit + limit; i++) {
  11. const item = list[i]
  12. const div = document.createElement('div')
  13. div.className = 'sunshine'
  14. div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
  15. container.appendChild(div)
  16. }
  17. render(page + 1)
  18. }, 0)
  19. }
  20. render(page)
  21. }

 在渲染页面的时候,我们可以使用requestAnimationFrame来代替setTimeout,这样可以减少reflow次数,提高性能。

  1. const renderList = async () => {
  2. const list = await getList()
  3. const total = list.length
  4. const page = 0
  5. const limit = 200
  6. const totalPage = Math.ceil(total / limit)
  7. const render = (page) => {
  8. if (page >= totalPage) return
  9. requestAnimationFrame(() => {
  10. for (let i = page * limit; i < page * limit + limit; i++) {
  11. const item = list[i]
  12. const div = document.createElement('div')
  13. div.className = 'sunshine'
  14. div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
  15. container.appendChild(div)
  16. }
  17. render(page + 1)
  18. })
  19. }
  20. render(page)
  21. }

二、从渲染上解决:

异步渲染,比如进入页面先不渲染,然后加载好页面再渲染。

局部渲染:只渲染目前可见区域的数据,再渲染次屏数据。

根据用户的滚动位置动态渲染数据。

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

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

  1. <script setup lang="ts">
  2. import { onMounted, ref, computed } from 'vue'
  3. const getList = () => {
  4. // code as before
  5. }
  6. const container = ref<HTMLElement>() // container element
  7. const blank = ref<HTMLElement>() // blank element
  8. const list = ref<any>([])
  9. const page = ref(1)
  10. const limit = 200
  11. const maxPage = computed(() => Math.ceil(list.value.length / limit))
  12. // List of real presentations
  13. const showList = computed(() => list.value.slice(0, page.value * limit))
  14. const handleScroll = () => {
  15. if (page.value > maxPage.value) return
  16. const clientHeight = container.value?.clientHeight
  17. const blankTop = blank.value?.getBoundingClientRect().top
  18. if (clientHeight === blankTop) {
  19. // When the blank node appears in the viewport, the current page number is incremented by 1
  20. page.value++
  21. }
  22. }
  23. onMounted(async () => {
  24. const res = await getList()
  25. list.value = res
  26. })
  27. </script>
  28. <template>
  29. <div id="container" @scroll="handleScroll" ref="container">
  30. <div class="sunshine" v-for="(item) in showList" :key="item.tid">
  31. <img :src="item.src" />
  32. <span>{{ item.text }}</span>
  33. </div>
  34. <div ref="blank"></div>
  35. </div>
  36. </template>

还有性能瓶颈,可以考虑web worker 做压缩和解码,也可以考虑离屏canvas做预渲染。

三、减少网络耗时:压缩数据,gzip等

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜