• React - 实现瀑布流加载


    React - 实现瀑布流加载

    一. 瀑布流实现

    先来看下原本的效果,一次性加载完所有的信息然后展示:
    在这里插入图片描述
    其次,我们需要去监听这个滚轮的滚动事件,那么React页面就可以添加一个监听器:

    useEffect(() => {
      // 初始化动作
      initData();
      // 指定事件是否在捕获或冒泡阶段执行。true - 事件句柄在捕获阶段执行
      window.addEventListener('scroll', handleScroll, true);
      // 一定要有这段代码,在关闭你的页面或者跳转的时候,要把对应的监听器移除
      return () => {
        window.removeEventListener('scroll', handleScroll, true);
      };
    }, [ ]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    那么这个handleScroll函数,就是用来在发生滚动事件的时候,你要做的事情。既然我们要实现瀑布流,那么自然而然的就是去后端请求数据。但是,请求数据得有一个前提:你的滚动条已经到达页面的底部了。

    dom元素有这么三个属性:

    • clientHeight:内容可视区域的高度。

    • scrollTop:滚动条在Y轴上的滚动距离。

    • scrollHeight:内容可视区域的高度加上溢出(滚动)的距离。

    判断滚动条到达底部的条件则为:

    scrollTop + clientHeight === scrollHeight
    
    • 1

    那么这个dom元素的依据是什么?你项目里面,哪一个标签下写了css,有滚动条,就应该取哪一个标签。例如我自己的项目有这么一段代码:请注意,我这里加了overflow

    <Content style={{ overflow: 'auto', marginLeft: 200, height: '100%' }} id='zong_Content'>
      <div style={{ minWidth: 1340 }}>
        {props.children}
      </div>
    </Content>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    对应的css元素:
    在这里插入图片描述
    对应
    在这里插入图片描述
    我把这里贴出来的本意是要告诉大家,你在写滚动条监听事件的时候,当你需要计算滚动的距离,你就要找对滚动条所在的标签,否则距离算出来就是错的。

    那么我这里的代码对应的就是:

    // 页面滚动
      const handleScroll = () => {
        const liveDom :any = document.getElementById('zong_Content');
        const clientHeight = liveDom.clientHeight;
        const scrollTop = liveDom.scrollTop;
        const scrollHeight = liveDom.scrollHeight;
        if (scrollTop + clientHeight === scrollHeight) {
          console.log('到底部了!');
        }
      };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    让我们来看看效果:
    在这里插入图片描述

    可见滚动条到达底部的时候,就能输出对应的字样。只不过我这里没有写请求后端数据的代码。但是别急。你们有没有注意到:

    1. 当你滚动条到达页面最底部的时候,确实打印出了到底部了!的字样。
    2. 但是当你滚动条往上滑一点点,再往下滑到底部的时候,还是会打印这样的字样。

    这样有什么问题?不妨试想一下,下面的请求数据伪代码如果写上会有什么效果:

    if (scrollTop + clientHeight === scrollHeight) {
      console.log('到底部了!');
      loadData();
    }
    
    • 1
    • 2
    • 3
    • 4

    当你调用了loadData();接口,但是后端数据还没有返回。假设用户在前端浏览器上,滚动条在最底部和上方来回滚动10次,那么就会请求10遍接口。就会有重复请求的问题。

    1.1 处理重复请求问题

    因此我们应该对代码做出如下修改:

    let loading = false;
    
    const loadData = async () => {
      if (!loading) {
        loading = true;
        await dispatch({
          type: 'live/getMusicItem',
          payload: {},
        });
        setLiveItems(liveItems => [].concat(...liveItems, ...arr));
        loading = false;
      }
    };
      
    const handleScroll = async () => {
      const liveDom :any = document.getElementById('zong_Content');
      const clientHeight = liveDom.clientHeight;
      const scrollTop = liveDom.scrollTop;
      const scrollHeight = liveDom.scrollHeight;
      if (scrollTop + clientHeight === scrollHeight) {
      	await loadData();
      }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    1. 那么第一次监听到滚动条到底部的时候,loading变量(全局)就会变为true
    2. 如果发生重复的底部监听动作(上述所说情况),loading变量为true,if判断不满足,不会发送第二次请求,什么也不做。
    3. 只有第一次请求处理完毕,loading变量才会变为false。才可以发起后续请求。

    最终效果如下:
    在这里插入图片描述
    关注右侧的滚动条即可(由于是假数据,因此页面感官上不明显)。

    到这里,瀑布流就实现完成了。你也可以在原来的基础上增加:

    • 瀑布流不能无限制往下拉,比如上面有100行数据的时候,就可以采用分页操作。参考斗鱼。
    • 分页后,就重新从瀑布最上方开始加载数据。
  • 相关阅读:
    Linux高性能服务器编程 学习笔记 第十一章 定时器
    ❤ hexo主题+Gitee搭建个人博客
    python使用字典暴力解析wifi密码
    37页数字乡村振兴智慧农业整体规划建设方案
    【网络奇遇记】那年我与计算机网络的初相识 —— 网络的体系结构
    【2024校招】2023-9-17 度小满信贷系统平台部后端一面
    RTD2513驱动板ODM/OEM方式
    Openjudge1.5答案(十一到十五题)
    四:MySQL日志管理、备份与恢复
    vue-waterfall2 实现瀑布流,及总结的问题
  • 原文地址:https://blog.csdn.net/Zong_0915/article/details/127688038