React - 实现瀑布流加载

React - 实现瀑布流加载

一. 瀑布流实现

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

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

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

dom元素有这么三个属性:

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

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

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

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

scrollTop + clientHeight === scrollHeight

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

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

对应的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. 但是当你滚动条往上滑一点点,再往下滑到底部的时候,还是会打印这样的字样。

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

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

当你调用了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. 那么第一次监听到滚动条到底部的时候,loading变量(全局)就会变为true
  2. 如果发生重复的底部监听动作(上述所说情况),loading变量为true,if判断不满足,不会发送第二次请求,什么也不做。
  3. 只有第一次请求处理完毕,loading变量才会变为false。才可以发起后续请求。

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

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

  • 瀑布流不能无限制往下拉,比如上面有100行数据的时候,就可以采用分页操作。参考斗鱼。
  • 分页后,就重新从瀑布最上方开始加载数据。
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要使用 `react-native-svg` 和 `react-native-svg-transformer` 加载本地 SVG 图像,你可以按照以下步骤进行操作: 1. 首先,确保你已经在项目中安装了 `react-native-svg` 和 `react-native-svg-transformer` 依赖。你可以通过运行以下命令来安装它们: ``` npm install react-native-svg react-native-svg-transformer ``` 2. 在项目的根目录下创建一个名为 `metro.config.js` 的文件(如果已存在,请跳过此步骤)。 3. 在 `metro.config.js` 文件中添加以下内容: ```javascript module.exports = { transformer: { assetPlugins: ['react-native-svg-transformer'], }, }; ``` 4. 接下来,在你的组件中,使用 `react-native-svg` 中的 `<SvgUri>` 组件来加载本地 SVG 图像。首先,确保你的 SVG 图像位于项目的 `assets` 文件夹中。 ```javascript import React from 'react'; import { View } from 'react-native'; import SvgUri from 'react-native-svg-uri'; const MyComponent = () => { return ( <View> <SvgUri width={200} height={200} source={require('./assets/myImage.svg')} /> </View> ); }; export default MyComponent; ``` 在上面的示例中,我们使用 `require` 方法加载位于 `assets` 文件夹中的 `myImage.svg` 图像,并将其作为 `source` 属性传递给 `<SvgUri>` 组件。你可以根据自己的需要调整宽度和高度。 5. 确保你在重新启动 Metro Bundler 之前完成了以上步骤。你可以通过运行以下命令重新启动 Metro Bundler: ``` npx react-native start --reset-cache ``` 这样,你就可以使用 `react-native-svg` 和 `react-native-svg-transformer` 成功加载和显示本地 SVG 图像了。 希望对你有所帮助!如有任何疑问,请随时提问。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zong_0915

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值