后端API一次返回10万条数据,前端如何处理

后端API一次返回10万条数据,前端如何处理

直接渲染 (不可取)

通过 setTimeout 进行分页渲染

  • 每个页面有条数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 = 'addText'
                      div.innerHTML = `<span>${item.text}</span>`
                      container.appendChild(div)
                  }
                  render(page + 1)
              }, 0)
          }
          render(page)
      }
    

requestAnimationFrame

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

  • window.requestAnimationFrame() 方法告诉浏览器您希望执行动画,并请求浏览器调用指定函数在下一次重绘之前更新动画

  • 同时可以先创建一个文档片段,在创建了 div 元素之后,再将元素插入到文档片段中。创建完所有 div 元素后,将片段插入页面,提高页面性能。

  • 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(() => {
                const fragment = document.createDocumentFragment()
                for (let i = page * limit; i < page * limit + limit; i++) {
                    const item = list[i]
                    const div = document.createElement('div')
                    div.className = 'addText'
                    div.innerHTML = `<span>${item.text}</span>`
                    fragment.appendChild(div)
                }
                container.appendChild(fragment)
                render(page + 1)
            })
        }
        render(page)
    }
    

延迟加载

  • 用户的屏幕只能同时显示有限的数据,所以我们可以采用延迟加载的策略,根据用户的滚动位置动态渲染数据

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

  • 同时,我们可以使用getBoundingClientRect来判断空白是否在页面底部,getBoundingClientRect()返回值是一个 DOMRect 对象,包含整个元素的最小矩形(包括 padding 和 border-width)。该对象使用 left、top、right、bottom、x、y、width 和 height 这几个以像素为单位的只读属性描述整个矩形的位置和大小

  • <script setup lang="ts">
    import { onMounted, ref, computed } from 'vue'
        
    const getList = () => {
      return new Promise((resolve, reject) => {
        var ajax = new XMLHttpRequest();
        ajax.open('get', 'http://127.0.0.1:8000');
        ajax.send();
        ajax.onreadystatechange = function () {
          if (ajax.readyState == 4 && ajax.status == 200) {
            resolve(JSON.parse(ajax.responseText))
          }
        }
      })
    }
    
    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) {
        // 当空白出现在页面底部,当前页数+1
        page.value++
      }
    }
    onMounted(async () => {
      const res = await getList()
      list.value = res
    })
    </script>
    
    <template>
      <div id="container" @scroll="handleScroll" ref="container">
        <div class="addText" v-for="(item) in showList" :key="item.tid">
          <span>{{ item.text }}</span>
        </div>
        <div ref="blank"></div>
      </div>
    </template>
    
    
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT枫斗者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值