web前端怎么更好的展示后端返回的十万条数据

技术web前端怎么更好的展示后端返回的十万条数据本篇内容主要讲解“web前端怎么更好的展示后端返回的十万条数据”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“web前端怎么更好

本文主要讲解“如何更好地展示web前端后端返回的10万条数据”。感兴趣的朋友不妨看看。本文介绍的方法简单、快速、实用。让边肖带你学习“web前端如何更好地展示后端返回的10万条数据”!

00-1010先把前期工作做好,之后我们再来测试。

00-1010新建一个server.js文件,简单的启动一个服务,返回10w条数据到前端,通过nodemon server.js启动服务

没有安装nodemon的学生可以先全局安装npm i nodemon -g。

//server.js

consthttp=require('http ')

constport=8000

http.createServer(函数(请求,资源){ 0

//打开Cors

res.writeHead(200,{ 0

//设置跨域域名或*允许所有域名。

访问控制允许来源' :'*,

//允许跨域请求方法,也可以设置*允许所有方法。

访问控制-允许-方法' : '删除,放,发布,获取,选项',

//允许的标题类型

访问控制-允许-标题' : '内容类型'

})

letlist=[]

letnum=0

//生成10万条数据的列表

for(leti=0;i1000000I){ 0

数字

list . push({ 0

src : ' https://p 3-passport . byteacctimg.com/img/user-avatar/d71c 38d 1682 c 543 b 33 F8 d 716 B3 b 734 ca ~ 300 x300 . image ',

短信:‘我是林三鑫,${num}的客人,

tid:num纳米

})

}

RES . end(JSON . stringify(list));

}).侦听(端口,函数(){ 0

console . log(' server islistingonport '端口);

})

前置工作

先建设新index.html。

//index.html

//样式

风格

*{

划水:0;

margin:0

}

#容器{

高度:100 VH;

飞越

ow: auto;
    }
    .sunshine {
      display: flex;
      padding: 10px;
    }
    img {
      width: 150px;
      height: 150px;
    }
  </style> 
// html部分
<body>
  <div id="container">
  </div>
  <script src="./index.js"></script>
</body>

然后新建一个 index.js 文件,封装一个 AJAX 函数,用来请求这 10w 条数据

// index.js 
// 请求函数
const getList = () => {
    return new Promise((resolve, reject) => {
        //步骤一:创建异步对象
        var ajax = new XMLHttpRequest();
        //步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数
        ajax.open('get', 'http://127.0.0.1:8000');
        //步骤三:发送请求
        ajax.send();
        //步骤四:注册事件 onreadystatechange 状态改变就会调用
        ajax.onreadystatechange = function () {
            if (ajax.readyState == 4 && ajax.status == 200) {
                //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
                resolve(JSON.parse(ajax.responseText))
            }
        }
    })
} 
// 获取container对象
const container = document.getElementById('container')

直接渲染

最直接的方式就是直接渲染出来,但是这样的做法肯定是不可取的,因为一次性渲染出 10w 个节点,是非常耗时间的,咱们可以来看一下耗时,差不多要消耗 12秒 ,非常消耗时间

const renderList = async () => {
    console.time('列表时间')
    const list = await getList()
    list.forEach(item => {
        const div = document.createElement('div')
        div.className = 'sunshine'
        div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
        container.appendChild(div)
    })
    console.timeEnd('列表时间')
}
renderList()

setTimeout分页渲染

这个方法就是,把 10w 按照每页数量 limit 分成总共 Math.ceil(total / limit) 页,然后利用 setTimeout ,每次渲染1页数据,这样的话,渲染出首页数据的时间大大缩减了

const renderList = async () => {
    console.time('列表时间')
    const list = await getList()
    console.log(list)
    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)
    console.timeEnd('列表时间')
}

requestAnimationFrame

使用 requestAnimationFrame 代替 setTimeout ,减少了 重排 的次数,极大提高了性能,建议大家在渲染方面多使用 requestAnimationFrame

const renderList = async () => {
    console.time('列表时间')
    const list = await getList()
    console.log(list)
    const total = list.length
    const page = 0
    const limit = 200
    const totalPage = Math.ceil(total / limit)
    const render = (page) => {
        if (page >= totalPage) return
        // 使用requestAnimationFrame代替setTimeout
        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)
        }, 0)
    }
    render(page)
    console.timeEnd('列表时间')
}

文档碎片 + requestAnimationFrame

文档碎片 的好处

1、之前都是每次创建一个 div 标签就 appendChild 一次,但是有了 文档碎片 可以先把1页的 div 标签先放进 文档碎片 中,然后一次性 appendChild  container 中,这样减少了 appendChild 的次数,极大提高了性能

2、页面只会渲染 文档碎片 包裹着的元素,而不会渲染 文档碎片

const renderList = async () => {
    console.time('列表时间')
    const list = await getList()
    console.log(list)
    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 = 'sunshine'
                div.innerHTML = `<img src="${item.src}" /><span>${item.text}</span>`
                // 先塞进文档碎片
                fragment.appendChild(div)
            }
            // 一次性appendChild
            container.appendChild(fragment)
            render(page + 1)
        }, 0)
    }
    render(page)
    console.timeEnd('列表时间')
}

懒加载

为了比较通俗的讲解,咱们启动一个 vue 前端项目,后端服务还是开着

其实实现原理很简单,咱们通过一张图来展示,就是在列表尾部放一个空节点 blank ,然后先渲染第1页数据,向上滚动,等到 blank 出现在视图中,就说明到底了,这时候再加载第二页,往后以此类推。

至于怎么判断 blank 出现在视图上,可以使用 getBoundingClientRect 方法获取 top 属性

<script setup lang="ts">
import { onMounted, ref, computed } from 'vue'
const getList = () => {
  // 跟上面一样的代码
}
const container = ref<HTMLElement>() // container节点
const blank = ref<HTMLElement>() // blank节点
const list = ref<any>([]) // 列表
const page = ref(1) // 当前页数
const limit = 200 // 一页展示
// 最大页数
const maxPage = computed(() => Math.ceil(list.value.length / limit))
// 真实展示的列表
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) {
    // blank出现在视图,则当前页数加1
    page.value++
  }
} 
onMounted(async () => {
  const res = await getList()
  list.value = res
})
</script> 
<template>
  <div class="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前端怎么更好的展示后端返回的十万条数据”有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/116532.html

(0)

相关推荐