jQuery无限加载瀑布流

瀑布流实现需求:

  1、ajax请求数据,渲染页面
  2、根据高度不同,自动排列位置 (封装位置函数)
  3、当滚动页面到最后一张图片之前时,ajax请求加载数据
  4、重复 3 操作 滚动页面加载数据
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="referrer" content="no-referrer" />
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body,
    html {
      height: 100%;
      background-color: #ddd;
    }

    li {
      list-style-type: none;
    }

    .container {
      width: 1000px;
      margin: 0 auto;
    }

    .container ul {
      width: 1100px;
    }

    .container ul::after {
      content: "";
      clear: both;
      display: block;
    }

    .container ul li {
      float: left;
      height: auto;
      margin: 0 20px 20px 0;
      border-top: 0 none;
      background-color: #fff;
      border-radius: 2px;
      width: 235px;
    }

    .container ul li img {
      width: 100%;
    }

    .container ul li p {
      width: 100%;
      line-height: 40px;
      padding-left: 10px;
    }
  </style>
</head>

<body>
  <!-- 瀑布流容器 -->
  <div class="container">
    <!-- 瀑布流定位容器 -->
    <ul class="wrapper">
      <!-- 每个瀑布流元素 -->
      <!-- <li>
        <img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
        <p>粘土手作希小怪</p>
      </li>
      <li>
        <img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
        <p>粘土手作希小怪</p>
      </li>
      <li>
        <img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
        <p>粘土手作希小怪</p>
      </li>
      <li>
        <img src="https://c-ssl.duitang.com/uploads/item/202004/21/20200421222241_TvCXF.thumb.400_0.jpeg" alt="">
        <p>粘土手作希小怪</p>
      </li> -->
    </ul>
  </div>


  <script src="./javascripts/libs/jquery.js"></script>
  <script src="./javascripts/jquery.waterfall.js"></script>
  <script>
    // 瀑布流实现需求:
    //   1、ajax请求数据,渲染页面
    //   2、根据高度不同,自动排列位置 (封装位置函数)
    //   3、当滚动页面到最后一张图片之前时,ajax请求加载数据
    //   4、重复 3 操作 滚动页面加载数据


    // 1. 发起请求渲染页面;
    $(function () {
      //1. 记录最后一个元素;
      var last_ele = null;
      // 2. 页面的高度获取;
      var clientHeight = document.body.clientHeight;
      // 3. 限制加载的变量(标记当前的加载状态);
      var loading = false;
      // 4. 接口数据;
      var next_start = 0;

      // 1. 发起请求;
      $.ajax({
        url: "http://localhost:3000/dt",
        data: {
          include_fields: "top_comments,is_root,source_link,item,buyable,root_id,status,like_count,sender,album,reply_count",
          filter_id: "手工DIY",
          start: next_start,
          _: Date.now()
        }
      })
        .then(function (res) {
          // 测试数据是否可以正常获取;
          // console.log(res);
          render(res.data.object_list);

          $(".wrapper li").waterFall({
            max_col: 4
          });

          // 最后一个元素高度此时才有;
          last_ele = $(".wrapper li:last");

          next_start = res.data.next_start;
        })

      // 2. 渲染页面;
      function render(list) {
        // 1. 根据数据拼接字符串;
        var html = "";
        for (var i = 0; i < list.length; i++) {
          // 当前图片的宽度;
          var n_w = 235;
          // 图片实际的宽度;
          var w = list[i].photo.width;
          // 图片的实际高度;
          var h = list[i].photo.height;
          // 当前图片的高度;
          var n_h = n_w / w * h;

          html += `<li>
            <img src="${list[i].photo.path}" height=${parseInt(n_h)}>
            <p>${list[i].msg}</p>
          </li>`
        }
        // 2. 把字符串放入页面之中;
        $(".wrapper").append(html);
      }

      // 无限加载 : 
      // 数据 : 
      //  1. 最后一个元素的offsetTop值;
      //  2. 页面的高度; 
      //  3. scrollTop;

      $(document).on("scroll", throttling(function () {
        // console.log(1);
        // 安全逻辑 : 如果 最后一个元素为null, 我们应该直接跳出逻辑;或者loading为false
        if (!last_ele || loading) {
          return false;
        }
        // 如果 页面的高度 + scrollTop 大于等于 最后一个元素的高度; 需要加载数据了;
        if (clientHeight + $("html,body").scrollTop() >= last_ele.offset().top) {
          // 逻辑 : 加载如果没有结束,就不再发起新的请求;
          loading = true;
          // 发送请求,渲染页面,瀑布流排序;
          $.ajax({
            url: "http://localhost:3000/dt",
            data: {
              include_fields: "top_comments,is_root,source_link,item,buyable,root_id,status,like_count,sender,album,reply_count",
              filter_id: "手工DIY",
              start: next_start,
              _: Date.now()
            }
          })
            .then(function (res) {
              // 测试数据是否可以正常获取;
              render(res.data.object_list);

              $(".wrapper li").waterFall({
                max_col: 4
              });

              // 最后一个元素高度此时才有;
              last_ele = $(".wrapper li:last");
              // 改变加载的值
              loading = false;
              next_start = res.data.next_start;
            })
        }
      }, 200))

      // 事件 节流: 
      function throttling(callback, delay) {
        var t = null;
        return function () {
          if (t !== null) {
            return false;
          }
          t = setTimeout(function () {
            t = null;
            callback();
          }, delay)
        }
      }
    })
  </script>
</body>

</html>

waterfall封装函数

// 1. 我们要把插件写在局部作用域之中; 防止变量冲突;
// 2. 在写代码之前加上两个分号;
// 为啥要加分号 : 
// 在这种情况下不加分号就错误了;
/*
(function(){

})()
(function(){

})
*/
// 3. 把jQuery当做局部变量传入进去;
// 3.1. 可以优化性能; 不用进行两次查找就可以访问到 jQuery 了;
// 3.2. 防止和别人的 $ 符号冲突;

;;
(function ($) {
  // 开发一个局部方法还是全局方法;

  // 以下两种方法二选一 : 

  // $.extend( $.fn , {
  //       waterFall : function(){

  //       }
  // })

  // 高度列表;
  var height_list = [];
  
  // 定义一个API方法
  $.fn.waterFall = function (options) {
    // 如果上一次的数组不清空,那么下次会沿用之前的数据导致数据失真;
    height_list.length = 0;
    // console.log("waterfall功能被调用,页面上的元素都排列好了");
    // 为什么在操作DOM的时候我们去使用原型方法;
    // this 指向实例对象;
    // console.log(this); //例如:原生中的DOM元素
    // 1. 前四个不动后面的都跟着前四个进行排列;
    // 为了防止出现问题,给options设置一波默认参数;
    options = $.extend({
      max_col: 4
    }, options);
    // 2. 遍历所有元素;
    // 所有的元素其实都放在 this 上;
    // this === 需要排列的元素;

    for (var i = 0; i < this.length; i++) {
      if (i < options.max_col) {
        // 第一排的元素,获取元素的高度作为每一列的基数;
        height_list.push(this.eq(i).height());
      } else {
        // 剩余的元素; 根据高度数组进行排列;
        // 找到数组之中的最小高度;

        // 技巧解释; 这是一个快速找到数组之中最小值的API;
        // 直接使用即可;
        // console.log(height_list) // 里面每次有四个值 求出四个值中最小高度
        var min_height = Math.min.apply(false, height_list);
        // 获取最小值的下标;
        var min_index = height_list.indexOf(min_height);
        // console.log(min_index)
        // 让元素进行拼接;
        // console.log(this.eq(i))
        this.eq(i).offset({
          // 最小下标那一列的left值;
          left: this.eq(min_index).offset().left,
          // 最小高度值;
          top: min_height + 20
        });
        // 改变高度数组;  这里 +20 是 margin 值
        height_list[min_index] += this.eq(i).height() + 20;
      }
    }
  }
})(jQuery);

注意:接口在gulp自动化构建的服务器中已经处理

码云地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值