前端瀑布流布局

瀑布流是一种流行的网站布局方式,以参差不齐的多栏设计节省空间并提供良好用户体验。它通过下拉加载数据,适用于手机端。文章介绍了使用js、css及createSelectorQuery计算高度的实现方法,并指出其可能导致的内容长度未知、定位困难等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

瀑布流布局



一、瀑布流介绍

1、什么是瀑布流

瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次按照规则放入指定位置。

2、为什么使用瀑布流

瀑布流布局在我们现在的前端页面中经常会用的到,它可以有效的降低页面的复杂度,节省很多的空间,对于整个页面不需要太多的操作,只需要下拉就可以浏览用户需要看到的数据;并且,瀑布流可以提供很好的用户体验,通过结合下拉刷新,上拉加载进行数据的懒加载等操作,对于用户的体验感来说是接近于满分的!

3、瀑布流的特点

其实瀑布流的特点就是参差不齐的排列方式,以及流式布局的扩展性,可以通过界面展示给用户多条数据,并且让用户可以有向下浏览的冲动。

4、瀑布流优点

节省空间,外表美观,更有艺术性。
对于手机端设备非常友好,通过向上滑动浏览。
用户浏览时的观赏和思维不容易被打断。

5、瀑布流缺点

用户无法了解内容总长度,对内容没有宏观掌控。
用户无法了解现在所处的具体位置,不知道离终点还有多远。
回溯时不容易定位到之前看到的内容。
容易造成页面加载的负荷。
容易造成用户浏览的疲劳,没有短暂的休息时间。

二、示例图片与网址

请添加图片描述
请添加图片描述
示例网址

二、代码实现方式

1.pc端js计算高度

思路:
1.获取要加载的元素,取第一个元素根据宽度计算视图窗口能展示几列。
2.根据能展示的列数设初始高度值。
3.遍历要排序的元素,判断最后一列高度比较找到高度最小的那个。
4.将当前元素定位到此处,更新当前列的高度

代码如下(示例):

      // 初始化图片位置
      var init = () => {
        // 1、获取所有的盒子  宽度都是固定的高度自适应
        var node = document.querySelectorAll('.item');
        // 2、获取第一个盒子的宽度+外边距  
        var nodeWidth = node[0].offsetWidth + 10;
        // 3、这里根据浏览器视口大小进行动态更新展示一排显示的个数
        var colCount = parseInt(document.body.offsetWidth / nodeWidth);
        // 4、定义一个数组保存最后一排的高度
        var colItemHeight = [];
        // 5、开始默认第一排都是为0
        for (var j = 0; j < colCount; j++) {
          colItemHeight.push(0);
        }
        // 6、遍历所有的盒子
        node.forEach(function (item) {
          // 7、假设第一排第一个为最小的高度
          var minHeight = colItemHeight[0];
          // 8、保存最小高度盒子的索引值
          var index = 0;
          // 9、遍历最新高度的数组
          colItemHeight.forEach(function (pro, idx) {
            // 10、判断最小高度是不是大于当前遍历到的高度
            if (minHeight > pro) {
              // 11、如果条件成立  将当前最小的高度重新复制给最小高度变量
              minHeight = pro;
              // 12、同时更新当前最小高度盒子的索引
              index = idx;
            }
          })
          // 13、获取到最小高度的盒子后  开始设置盒子的定位
          item.style.top = minHeight + 'px';
          item.style.left = (nodeWidth * index) + 'px';
          // 14、动态更新,最新高度等于 盒子的高度+外边距+之前高度
          colItemHeight[index] = (item.offsetHeight + 10) + colItemHeight[index];
        })
      }

2.css实现

思路:
column-width: 200px;
//把元素中的文本划分为几列布局
column-count: auto;
//指定列之间的的间隙:
column-gap: 40px;

代码如下(示例):

  .waterfall {
    column-width: 200px;
    column-count: auto;
    column-gap: 1rem;
  }

3.createSelectorQuery节点查询计算高度

思路:
根据createSelectorQuery 获取当前节点
分为左右两侧盒子,循环计算高度添加到两侧

代码如下(示例):

 const getDataDom = async () => {
    // Taro.showLoading({
    //   title: "数据加载中",
    //   mask: true,
    // });
    let _leftList = [],
      _rightList = [];
    for (let item in data) {
      // 要有固定内容先将内容判断高度。
      await getBoxHeight(_leftList, _rightList);
      // 判断两边的高度
      // console.log(leftHeightRef.current, rightHeightRef.current)
      if (leftHeightRef.current <= rightHeightRef.current) {
        _leftList.push(data[item]);
        setLeftList([..._leftList]);
      } else {
        _rightList.push(data[item]);
        setRightList([..._rightList]);
      }
    }
    // Taro.hideLoading()
  };

  const getBoxHeight = () =>
    new Promise((resolve, reject) => {
      query = Taro.createSelectorQuery();
      query.select("#dis_left").boundingClientRect();
      query.select("#dis_right").boundingClientRect();
      // 处理异步问题,没有数据
      setTimeout(() => {
        query.exec((res) => {
          // console.log(res, res[0].height, res[1].height)
          leftHeightRef.current = res[0].height; //获取左边列表的高度
          rightHeightRef.current = res[1].height; //获取右边列表的高度
          resolve();
        });
      });
    });
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值