本文主要讲解“如何更好地展示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
