前端如何优化大量数据处理
admin 阅读: 2024-04-01
后台-插件-广告管理-内容页头部广告(手机) |
一、从数据上处理:
分页分表,比如前端可以把数据分页展示,后端也分段吐数据
对数据进行分页。假设每个页面都有limit记录,那么数据可以分为Math.ceil(total/limit)个页面。之后,我们可以使用 setTimeout 顺序渲染页面,一次只渲染一个页面。
- const renderList = async () => {
- const list = await getList()
- const total = list.length
- const page = 0
- const limit = 200
- const totalPage = Math.ceil(total / limit)
- const render = (page) => {
- if (page >= totalPage) return
- setTimeout(() => {
- for (let i = page * limit; i < page * limit + limit; i++) {
- const item = list[i]
- const div = document.createElement('div')
- div.className = 'sunshine'
- div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
- container.appendChild(div)
- }
- render(page + 1)
- }, 0)
- }
- render(page)
- }
在渲染页面的时候,我们可以使用requestAnimationFrame来代替setTimeout,这样可以减少reflow次数,提高性能。
- const renderList = async () => {
- const list = await getList()
- const total = list.length
- const page = 0
- const limit = 200
- const totalPage = Math.ceil(total / limit)
- const render = (page) => {
- if (page >= totalPage) return
- requestAnimationFrame(() => {
- for (let i = page * limit; i < page * limit + limit; i++) {
- const item = list[i]
- const div = document.createElement('div')
- div.className = 'sunshine'
- div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
- container.appendChild(div)
- }
- render(page + 1)
- })
- }
- render(page)
- }
二、从渲染上解决:
异步渲染,比如进入页面先不渲染,然后加载好页面再渲染。
局部渲染:只渲染目前可见区域的数据,再渲染次屏数据。
根据用户的滚动位置动态渲染数据。
要获取用户的滚动位置,我们可以在列表末尾添加一个空节点空白。每当视口出现空白时,就意味着用户已经滚动到网页底部,这意味着我们需要继续渲染数据。
同时,我们可以使用getBoundingClientRect来判断空白是否在页面底部。
- <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) {
- // When the blank node appears in the viewport, the current page number is incremented by 1
- 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) in showList" :key="item.tid">
- <img :src="item.src" />
- <span>{{ item.text }}</span>
- </div>
- <div ref="blank"></div>
- </div>
- </template>
还有性能瓶颈,可以考虑web worker 做压缩和解码,也可以考虑离屏canvas做预渲染。
三、减少网络耗时:压缩数据,gzip等
声明
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |