第124题 后端一次性返回十万条数据,你该如何渲染
- 设计不合理
- 后端返回十万条数据,本身技术方案设计就不合理(一般情况都是分页返回,返回十万条浏览器渲染是一个问题,十万条数据加载也需要一个过程)
- 后端的问题,要用后端的思维去解决-中间层
- 浏览器能否处理十万条数据?
- 渲染到
DOM上会非常卡顿
- 渲染到
- 方案1:自定义中间层
- 自定义
nodejs中间层,获取并拆分这十万条数据 - 前端对接
nodejs中间层,而不是服务端 - 成本比较高
- 自定义
- 方案2:虚拟列表
- 只创建可视区的
DOM(比如前十条数据),其他区域不显示,根据数据条数计算每条数据的高度,用div撑起高度 - 随着浏览器的滚动,创建和销毁
DOM - 虚拟列表实现起来非常复杂,工作中可使用第三方库(
vue-virtual-scroll-list、react-virtualiszed) - 虚拟列表只是无奈的选择,实现复杂效果而效果不一定好(低配手机)
- 只创建可视区的

分页加载示例
前端通过与后端约定的分页接口,逐页请求数据并渲染。通过控制每页的数据量,可以在不影响性能的情况下展示大量数据。
// 前端代码
const pageSize = 100; // 每页数据量
let currentPage = 1; // 当前页数
function fetchData(page) {
// 发送请求到后端,获取指定页数的数据
fetch(`/api/data?page=${page}&pageSize=${pageSize}`)
.then(response => response.json())
.then(data => {
// 渲染数据到页面
renderData(data);
});
}
function renderData(data) {
// 将数据渲染到页面中
// ...
}
// 初始化加载第一页数据
fetchData(currentPage);
// 后端代码(示例使用 Express 框架)
app.get('/api/data', (req, res) => {
const page = req.query.page;
const pageSize = req.query.pageSize;
// 从数据库或其他数据源获取指定页数的数据
const data = getDataFromDatabase(page, pageSize);
res.json(data);
});
虚拟列表滚动示例
虚拟列表是一种优化技术,它只渲染当前可见区域内的数据,而不是一次性渲染全部数据。这样可以提高页面的加载速度和性能。
// 前端代码
const container = document.getElementById('data-container');
const itemHeight = 40; // 每项数据的高度
const visibleItems = Math.ceil(container.offsetHeight / itemHeight); // 可见区域内显示的项数
const totalItems = 100000; // 总数据量
function renderData(startIndex) {
const endIndex = Math.min(startIndex + visibleItems, totalItems);
for (let i = startIndex; i < endIndex; i++) {
const item = createItem(i);
container.appendChild(item);
}
}
function createItem(index) {
const item = document.createElement('div');
item.innerText = `Item ${index + 1}`;
item.style.height = `${itemHeight}px`;
return item;
}
// 监听滚动事件,动态渲染数据
container.addEventListener('scroll', () => {
const scrollTop = container.scrollTop;
const startIndex = Math.floor(scrollTop / itemHeight);
// 清空容器中的旧数据
container.innerHTML = '';
// 渲染当前可见区域内的数据
renderData(startIndex);
});
// 初始渲染首屏数据
renderData(0);
在上述示例中,通过监听滚动事件,根据滚动位置动态计算当前可见区域内的数据项的索引,并根据索引来渲染数据。随着用户滚动页面,会根据滚动位置不断重新渲染可见区域内的数据,而不会一次性渲染全部数据。
