RN瀑布流

背景

电商以及图片网站经常可以看到瀑布流的列表,即多列等宽的列表,但是每一列中的元素高度不一定一致。这在 web 是一个很常见的设计且有很多组件可供使用,而在 ReactNative 中,少有成熟的瀑布流组件,大多数组件要么是多年前维护的,要么 star 数较少,或者干脆有一些不维护了,总之就是用着不放心。因此在产品同学的要求下,实现了一个 RN 瀑布流组件。这里只记录思路,具体代码后面添加了较多业务相关的,就不贴了。

需求

  1. 支持上拉加载,下拉刷新

  2. 支持多列可定制

  3. 性能尽量好

  4. 自定义元素

思路

  1. 整个瀑布流通过 FlatList 来实现,通过设置 columnsNum 与 renderItem,将每一列又分别渲染成一个 FlatList。内层并列的 FlatList 将会撑开且不会产生多余的滚动条,滚动时是外层的 FlatList。

  2. 接收 data 时,判断每一项应该属于哪一列, 如果项的高度不能提前获得,那么要在项的 onLayout 时获取高度,之后判断下一项属于哪一列

  3. 下拉采用 RN 提供的 RefreshControl 就可以完成,而上拉的事件,单列表可以通过 onReachEnd 触发,而对于我们这种实现方式则只能通过 onScroll 自行判断是否到达底部

    // 由于 onEndReached 在渲染 data 项时会多次触发,且 props 及 state 未变化时不会触发,因此自行实现
    const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
      const {
        nativeEvent: {
          contentOffset: { y: scrollTop },
          contentSize: { height: scrollHeight },
          layoutMeasurement: { height },
        },
      } = event;
      if (scrollHeight - height - scrollTop <= onEndReachedThreshold) {
        if (onEndReached) {
          onEndReached(event);
        }
      }
      if (props.onScroll) {
        props.onScroll(event);
      }
    };

这样一个简单的 瀑布流就完成了。