第124题 后端一次性返回十万条数据,你该如何渲染

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

在上述示例中,通过监听滚动事件,根据滚动位置动态计算当前可见区域内的数据项的索引,并根据索引来渲染数据。随着用户滚动页面,会根据滚动位置不断重新渲染可见区域内的数据,而不会一次性渲染全部数据。

Last Updated:
Contributors: leeguooooo