用 React-vant 瀑布流组件轻松实现高颜值布局 🚀

132 阅读4分钟

作为前端开发者,咱们都知道实现瀑布流时踩过的坑 —— 计算列高算到脱发、动态加载时布局错乱、适配不同屏幕尺寸愁到失眠... 但自从发现了 React-vant 的 Waterfall 组件,我直呼 "早干嘛去了"!今天就带各位小白同学解锁这个宝藏组件,从此瀑布流开发效率翻倍👇

先看个开胃菜:什么是 React-vant?

image.png

React-vant 是有赞团队基于 React 开发的移动端组件库,就像前端界的 "预制菜"—— 把常用功能封装成即拿即用的组件,而 Waterfall 就是其中专门处理瀑布流布局的 "王牌选手"。它不仅帮我们搞定了复杂的列高计算,还自带加载更多、下拉刷新等功能,简直是懒人福音😴

上手实操:从 0 到 1 实现瀑布流

image.png

第一步:安装依赖(别告诉我你不会 npm 哦)

npm i react-vant --save
# 或者用yarn党最爱的方式
yarn add react-vant

第二步:基础结构搭建(比搭积木还简单)

先看个最基础的示例,感受下 React-vant 的优雅:

import { Waterfall, WaterfallItem } from 'react-vant';

function MyWaterfall() {
  // 模拟一组图片数据,实际项目里可能从接口获取
  const items = [
    { id: 1, imgUrl: '/img1.jpg', height: 200 },
    { id: 2, imgUrl: '/img2.jpg', height: 300 },
    { id: 3, imgUrl: '/img3.jpg', height: 250 },
    // ...更多数据
  ];

  return (
    <Waterfall columnCount={2} gap={10}>
      {items.map(item => (
        <WaterfallItem key={item.id} height={item.height}>
          <img 
            src={item.imgUrl} 
            style={{ width: '100%', height: '100%', objectFit: 'cover' }} 
            alt="瀑布流图片"
          />
        </WaterfallItem>
      ))}
    </Waterfall>
  );
}

这里有两个核心组件划重点:

  • <Waterfall>:容器组件,通过columnCount设置列数(手机端通常 2 列),gap控制间距
  • <WaterfallItem>:子项组件,必须指定height属性(这是保证布局正确的关键!)

第三步:进阶玩法:动态加载更多

刷抖音、逛小红书时那种 "滑到底部自动加载" 的功能,用 Waterfall 实现超简单:

function LoadMoreWaterfall() {
  const [list, setList] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);

  // 模拟接口请求
  const fetchData = async () => {
    if (loading) return;
    setLoading(true);
    // 实际项目里替换成真实接口
    const res = await mockApi.get('/items', { page, pageSize: 10 });
    setList(prev => [...prev, ...res.data]);
    setHasMore(res.hasMore);
    setPage(prev => prev + 1);
    setLoading(false);
  };

  // 初始加载
  useEffect(() => {
    fetchData();
  }, []);

  return (
    <Waterfall
      columnCount={2}
      gap={10}
      onLoadMore={hasMore ? fetchData : null}
      loadMoreLoading={loading}
    >
      {list.map(item => (
        <WaterfallItem key={item.id} height={item.height}>
          <img src={item.imgUrl} style={{ width: '100%', height: '100%' }} />
          <div className="item-desc">{item.title}</div>
        </WaterfallItem>
      ))}
    </Waterfall>
  );
}

关键属性解析:

  • onLoadMore:滚动到底部时触发的加载函数
  • loadMoreLoading:控制加载状态(显示 loading 动画)
  • 记得用hasMore控制是否继续加载,避免无效请求

避坑指南:这些错误新手常犯 😱

image.png

  1. 忘记设置 item 高度:导致布局错乱,记住WaterfallItem必须传height!如果是图片,可以先用imgnaturalHeight获取原始高度再计算
  2. 图片加载后高度变化:解决办法是给图片加onLoad事件,更新 item 高度:
<WaterfallItem 
  height={imgHeight}
  onLoad={() => setImgHeight(imgRef.current.offsetHeight)}
>
  <img ref={imgRef} src={url} />
</WaterfallItem>
  1. 列数设置不合理:手机端建议 2 列,平板最多 3 列,不然内容会挤成一团
  2. 没有处理加载失败:实际项目中要给fetchData加 try/catch,失败时允许用户重试

为什么推荐用组件库?

image.png

可能有同学会说 "我用原生 JS 也能写",但对比之下就知道差距:

  • 原生实现需要自己监听滚动、计算列高、处理重排,代码量至少 200 行

  • React-vant 组件已经做好了性能优化(比如防抖处理、虚拟列表)

  • 自带适配各种屏幕尺寸的样式,不用自己写媒体查询

就像开车 vs 走路,虽然都能到目的地,但效率差太远啦!

最后送份福利:完整示例代码

image.png

import { useState, useEffect, useRef } from 'react';
import { Waterfall, WaterfallItem, Toast } from 'react-vant';

const WaterfallDemo = () => {
  const [items, setItems] = useState([]);
  const [loading, setLoading] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const pageRef = useRef(1);

  // 模拟获取数据
  const getItems = async () => {
    if (loading) return;
    setLoading(true);
    try {
      // 模拟网络请求延迟
      await new Promise(resolve => setTimeout(resolve, 1000));
      const newItems = Array(8).fill(0).map((_, i) => ({
        id: `${pageRef.current}-${i}`,
        // 随机高度让瀑布流效果更明显
        height: 200 + Math.random() * 300,
        url: `https://picsum.photos/400/${200 + Math.random() * 300}`
      }));
      setItems(prev => [...prev, ...newItems]);
      pageRef.current++;
      // 模拟只有5页数据
      if (pageRef.current > 5) setHasMore(false);
    } catch (e) {
      Toast('加载失败,请重试');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    getItems();
  }, []);

  return (
    <div style={{ padding: 10 }}>
      <h3 style={{ padding: 10 }}>React-vant瀑布流示例 📸</h3>
      <Waterfall
        columnCount={2}
        gap={10}
        onLoadMore={hasMore ? getItems : null}
        loadMoreLoading={loading}
      >
        {items.map(item => (
          <WaterfallItem key={item.id} height={item.height}>
            <div style={{ 
              borderRadius: 8, 
              overflow: 'hidden', 
              backgroundColor: '#f5f5f5' 
            }}>
              <img 
                src={item.url} 
                style={{ width: '100%', height: '100%', objectFit: 'cover' }} 
                alt="示例图片"
              />
            </div>
          </WaterfallItem>
        ))}
      </Waterfall>
    </div>
  );
};

export default WaterfallDemo;

把这段代码复制到你的项目里,就能看到一个带加载更多功能的瀑布流啦!是不是超简单?

其实前端开发的秘诀就是:善用优秀的工具库,把精力放在业务逻辑上。React-vant 的 Waterfall 组件还有很多高级功能,比如自定义加载样式、下拉刷新等,大家可以去官方文档深入探索哦。

下次再遇到瀑布流需求,可别再傻傻自己写啦,用 React-vant 分分钟搞定,剩下的时间摸鱼不香吗?😉 有任何问题欢迎在评论区交流,我会一一解答~