Lists and tables scroll to the bottom to load data schemes

Lists and tables scroll to the bottom to load data schemes

foreword

Scrolling loading is a business scenario often encountered by the front end. It is mainly to realize the loading of lists. Its essence is not much different from paging. If there is no special requirement, paging can be used instead. The following solutions are made based on comprehensive performance and usage.

plan

1. Native js implementation

1. Use onScrollEvent to monitor whether the element wrapped by the div has scrolled to the bottom, and initiate the request again. ps:ref is the syntax of react, and its purpose is to store a variable. You can use let to define a variable to store natively.

<div ref={
    
    scrollElement} onScrollCapture={
    
    onScrollEvent}>
   <Table />
</div>

const onScrollEvent = (e) => {
    
    
    /** 解决横向滚动误触发判断 */
    if (e.target.scrollTop === scrollElement.current) return false;
    scrollElement.current = e.target.scrollTop;
    if (e.target.scrollTop === e.target.scrollHeight - e.target.clientHeight) {
    
    
      // setTableLoading(true);

      // console.log('我到底了,重新请求数据');
      setTimeout(() => {
    
    
        // setTableLoading(false);
      }, 100);
    }
  };

2. Realized by IntersectionObserver

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>滚动加载示例</title>
    <style>
      body {
    
    
        margin: 0;
        padding: 0;
        font-family: Arial, sans-serif;
      }

      .container {
    
    
        display: flex;
        flex-wrap: wrap;
        margin: 20px;
      }

      .item {
    
    
        flex-basis: 200px;
        height: 200px;
        margin: 10px;
        text-align: center;
        background-color: #f2f2f2;
        font-size: 36px;
        line-height: 200px;
      }

      .loading {
    
    
        height: 50px;
        text-align: center;
        font-size: 24px;
        color: #999;
        margin-bottom: 20px;
      }

      ::-webkit-scrollbar {
    
    
        width: 6px;
      }

      ::-webkit-scrollbar-thumb {
    
    
        border-radius: 3px;
        -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
        background-color: rgba(0, 0, 0, 0.2);
      }

      ::-webkit-scrollbar-track {
    
    
        -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
        border-radius: 3px;
        background-color: #f2f2f2;
      }
    </style>
  </head>

  <body>
    <div class="container"></div>
    <div class="loading">加载中...</div>
    <script>
      // 初始化数据
      const data = [];
      for (let i = 1; i <= 20; i++) {
    
    
        data.push(i);
      }

      // 创建 IntersectionObserver 实例
      const observer = new IntersectionObserver(
        (entries) => {
    
    
          // 遍历所有进入视口的元素
          entries.forEach((entry) => {
    
    
            // 如果元素是 loading 元素,且进入了视口,则执行加载更多数据的回调函数
            if (
              entry.target === document.querySelector(".loading") &&
              entry.isIntersecting
            ) {
    
    
              loadMore();
            }
          });
        },
        {
    
    
          root: null, // 使用浏览器视口作为根元素
          rootMargin: "0px", // 不设置边距
          threshold: 1.0, // 只有当目标元素全部进入视口时触发回调函数
        }
      );

      // 页面加载完毕后,先加载前面的数据
      window.onload = () => {
    
    
        const container = document.querySelector(".container");
        data.forEach((item) => {
    
    
          const el = document.createElement("div");
          el.className = "item";
          el.textContent = item;
          container.appendChild(el);
        });

        // 开始监听 loading 元素
        observer.observe(document.querySelector(".loading"));
      };

      // 加载更多数据的回调函数
      function loadMore() {
    
    
        // 模拟异步请求数据
        const newData = [];
        for (let i = 1; i <= 10; i++) {
    
    
          newData.push(data.length + i);
        }
        // 将新数据添加到页面中
        const container = document.querySelector(".container");
        newData.forEach((item) => {
    
    
          const el = document.createElement("div");
          el.className = "item";
          el.textContent = item;
          container.appendChild(el);
        });

        // 如果数据已经加载完毕,则取消监听 loading 元素
        if (data.length >= 50) {
    
    
          observer.unobserve(document.querySelector(".loading"));
          document.querySelector(".loading").textContent = "已加载全部数据";
        } else {
    
    
          data.push(...newData);
        }
      }
    </script>
  </body>
</html>

2. Use third-party components

It can be implemented using infinite-scrolla third-party library. Vue and react have corresponding versions of
react: react-infinite-scroll-component
vue:vue-infinite-scroll

3. Virtual list

If the page uses native js and other solutions, although the purpose can be achieved, as the page scrolls, the DOM elements of the page will increase a lot. In terms of comprehensive performance, it is recommended to use virtual tables. The latest versions of antd and element-plus already support virtual tables. Table scheme, refer to the corresponding writing method by yourself

react:https://ant.design/components/table-cn#components-table-demo-virtual-list
vue:https://element-plus.org/zh-CN/component/table-v2.html

Guess you like

Origin blog.csdn.net/weixin_53334387/article/details/130521901