前端攻城狮---AJAX(瀑布流的编写与应用)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gaoyouhuang/article/details/81914573

本章节主要是讲解瀑布流的集中编写方式和结合ajax的下拉加载更多。下面看看效果图是的

瀑布流方式一:依次排列

什么叫依次排列呢?就是所有的item从左到右依次排列,当超过父view的宽度时,换行继续排列。

效果图如下:

里面的数字其实就是一张张图片。我们先来看看布局

    <div class="waterfall">
        <div class="grid">
            <img src="images/0.png" alt="">
            <p>图片描述图片描述图片描述图片描述图片描述图片描述图片描述图片描述</p>
        </div>
        <div class="grid">
            <img src="images/1.png" alt="">
            <p>图片描述图片描述图片描述图片描述图片描述图片描述图片描述图片描述</p>
        </div>
        ...省略上诉同样的布局
    </div>

下面是css代码

 <style type="text/css">
        * {
            padding: 0;
            margin: 0
        }
        body {
            background-color: #ccc;
        }
        .waterfall {
            width: 800px;
            margin: 0 auto;
            position: relative;
        }
        .grid {
            width: 240px;
            position: absolute;
            background-color: #fff;
            padding: 10px;
            border-radius: 15px;
        }
        .grid img {
            width: 240px;
        }
    </style>

我们只给图片设置宽度,高度根据图片的尺寸自适应,从而实现瀑布流。

下面是js代码

    <script src="js/jquery.js"></script>
    <script>
         // 1得到所有的grid
         var $grids = $(".grid");
         // 2 循环去设置位置
         $grids.each(function() {
             var sum = 0;
             for(var i=$(this).index()-3;i>=0; i-=3) {
                 sum += $grids.eq(i).outerHeight()+20
             }
             $(this).css({
                 "left": ($(this).index()%3)*270,
                 "top": sum
             });
         });
         //  0  1  2 $(this).index()   top :全部 0  left: 0  270 540
         //  3  4  5  index%3  top 上面人的总高度  left 0 270 540
         //  6  7  8
         //  9  10 11
    </script>

因为一行排列三个,每个grid的总宽度是240+10+10=260,所以每一个grid之间的间隔是10,因为总宽度是800.

left:

      首先 每一行的第一个grid的left应该是0  第二个是270=260+10,第三个是540=260*2+10*2

      所以 我们可以得出一个关系式,每一个gril对应的下标除以3的余数*270等于对应gril的left

top:

      每一个gril的top,应该是该top上面所有的高度之和。如第6个,他的top应该是3 和 0的高度之和。

      所以我们可以得出一个循环关系式,也就是自身下标依次减3,获取其高度进行累加。为了美观,我们加了20的间距。

但是这样子的排列也有弊端,因为每个item的高度参差不齐,会出现下面这种效果

因为有些item的高度太小了,就会出现这种效果,确实不好看,那么来了解一下另外一种瀑布流的布局方式。

瀑布流方式二:谁低排谁下面

名字就同排列方法一样,该方式就是插入式,哪一列高度最小排哪列下面,这样就可以避免了上面那种情况。

css和样式同上面一模一样,下面来看看js部分

    <script src="js/jquery.js"></script>
    <script src="js/underscore.js"></script>
    <script>
       // 
       window.onload = function() {
          // 思路二  格子看哪列最矮 插入到哪里
        // 得到所有格子
        var $grids = $(".grid");
        //用数组存储当前三列的总高度
        var colHeight = [0,0,0];
        // 循环遍历每个格子              
        $grids.each(function() {
            // 求当前列最短值
            var minHeight = _.min(colHeight);
            //alert(minHeight);
            //  找到最短值的列序号
            var minIndex = _.indexOf(colHeight,minHeight);
            $(this).css({
                "top":minHeight,
                "left":minIndex*270
            });
            // 设置当前插入最短列的总高度
            colHeight[minIndex] += $(this).outerHeight()+20;
        });
       } 
    </script>

首先,我们创建了一个colHeight来存放每一列的高度,默认是0,

其次,去循环所有的gril,选出colHeight中最小的值和对应的下标,因为下标的值只有0 1 2,就直接乘以270,来表示left

           取出colHeight中最小的值来当做top,并将自己的高度加上最小的值,重新赋予该下标对应的值。

最后不断的循环,出现了瀑布流。

我们来看看效果图

排列的顺序不是123455这样的有序排列了,而是哪一列高度最小排列到其下面。

瀑布流结合ajax的下拉刷新

接下来到了重头戏,我们将结合前面所学的ajax请求,接合模块化去实现这个下拉刷新的瀑布流。

首先我们修改一下布局,添加了loading,将里面的item写成模块化.

  <div class="waterfall" id="waterfall">
    </div>
    <div class="loading">
        正在加载....
    </div>
    <script type="text/template" id="grid_template">
        <div class="grid">
                <img src="<%=imgurl %>" alt="">
                <p><%=content%></p>
                <p><%=author%></p>
            </div>
    </script>
    <script src="js/jquery.js"></script>
    <script src="js/underscore.js"></script>
    //css 其他同上
      .loading {
            width: 400px;
            margin: 0 auto;
            line-height: 30px;
            background-color: gold;
            color: white;
            text-align: center;
            font-size: 14px;
        }

js代码部分大体上分两部分,模块化加载数据  监听滑动距离,实现下拉加载更多

模块化加载数据

        var $waterfall = $("#waterfall");
        // 得到模板字符串
        var templateStr = $("#grid_template").html();
        //  生成数据绑定函数
        var compile = _.template(templateStr);
        //用数组存储当前三列的总高度
        var colHeight = [0, 0, 0];
        var page = 1;
        getJsonandRender(page);
   

1.我们使用underscore.js去实现模块化,具体使用请看ajax(3),然后去调用getJsonandRender方法去获取对应分页的数据,page是会自增的.

  function getJsonandRender(page) {
            // 发get请求
            $.get("json/json" + page + ".txt", function (data) {
                // data转成json对象
                var dataObj = JSON.parse(data);
                // 进行有没有到数据结束判断
                if(dataObj.news.length===0) {
                    console.log("没有数据了");
                    $(".loading").show().html("没有更多的数据");
                    return;
                }
        }

2.调用接口去获取到数据,接口中传去page,为了配合分页加载.当加载不到数据时,则认为加载完毕,则会在最底下去显示加载完毕字样.

       _.each(dataObj.news, function (dictionary) {
                    // 谁先加载完毕 处理谁
                    var image = new Image();
                    // 一旦设置了src属性 图片就开始加载
                    image.src = dictionary.imgurl;
                    $(image).load(function () {
                        var domStr = compile(dictionary);
                        var $grid = $(domStr);
                        $waterfall.append($grid);
                        // 给grid定位
                        // 求当前列最短值
                        var minHeight = _.min(colHeight);
                        //  找到最短值的列序号
                        var minIndex = _.indexOf(colHeight, minHeight);
                        $grid.css({
                            "top": minHeight,
                            "left": minIndex * 270
                        });
                        // 设置当前插入最短列的总高度
                        colHeight[minIndex] += $grid.outerHeight() + 20;
                        // 给最大的盒子设置高度
                        $waterfall.css("height",_.max(colHeight));
                        // 隐藏loading
                        $(".loading").hide();
                    });
                });
                lock = true;
            });

3.我们在遍历数据去渲染显示的时候,为了保证图片是加载完毕再进行排列显示,我们将瀑布流排列的核心代码放在了load方法的回调里.当只要有一个item加载完毕,则去隐藏loading视图.其中lock是为了配合界面滑动,后面会说.

以上三个步骤,我们实现了加载第一页的数据.

监听滑动距离,实现下拉加载更多

  // 给窗口监听滚
        var lock = true;
        $(window).scroll(function() {
             if(!lock) return;
             // 当滚动到快到底的时候 再次发ajax请求
             console.log($(window).scrollTop());
             console.log($(document).height()-$(window).height());
             var rate = $(window).scrollTop()/($(document).height()-$(window).height());
             if(rate>=0.75) {
                 page++;
                 getJsonandRender(page);
                 lock = false;
             }
        });

lock的作用就是为了保证上一页加载完毕之后,再加载下一页,也就是限流,防止加载时数据显示错乱.

我们这里下拉加载更多的依据就是当滚动的距离超过了页面的高度的百分之75,择取加载更多.

     $(window).scrollTop() : 表示窗口滚动的距离

     $(window).height() : 表示窗口的高度(固定不变的)

     $(document).height() : 表示body整个的个高度

下面来上传一个完整代码

   <script>
        // 得到大盒子
        var $waterfall = $("#waterfall");
        // 得到模板字符串
        var templateStr = $("#grid_template").html();
        //  生成数据绑定函数
        var compile = _.template(templateStr);
        //用数组存储当前三列的总高度
        var colHeight = [0, 0, 0];
        var page = 1;
        getJsonandRender(page);
        // 请求数据并渲染
        function getJsonandRender(page) {
            // 发get请求
            $.get("json/json" + page + ".txt", function (data) {
                // data转成json对象
                var dataObj = JSON.parse(data);
                // 进行有没有到数据结束判断
                if(dataObj.news.length===0) {
                    console.log("没有数据了");
                    $(".loading").show().html("没有更多的数据");
                    return;
                }
                _.each(dataObj.news, function (dictionary) {
                    // 谁先加载完毕 处理谁
                    var image = new Image();
                    // 一旦设置了src属性 图片就开始加载
                    image.src = dictionary.imgurl;
                    $(image).load(function () {
                        var domStr = compile(dictionary);
                        var $grid = $(domStr);
                        $waterfall.append($grid);
                        // 给grid定位
                        // 求当前列最短值
                        var minHeight = _.min(colHeight);
                        //  找到最短值的列序号
                        var minIndex = _.indexOf(colHeight, minHeight);
                        $grid.css({
                            "top": minHeight,
                            "left": minIndex * 270
                        });
                        // 设置当前插入最短列的总高度
                        colHeight[minIndex] += $grid.outerHeight() + 20;
                        // 给最大的盒子设置高度
                        $waterfall.css("height",_.max(colHeight));
                        // 隐藏loading
                        $(".loading").hide();
                    });
                });
                lock = true;
            });
        }
        // 给窗口监听滚
        var lock = true;
        $(window).scroll(function() {
             if(!lock) return;
             // 当滚动到快到底的时候 再次发ajax请求
             console.log($(window).scrollTop());
             console.log($(document).height()-$(window).height());
             var rate = $(window).scrollTop()/($(document).height()-$(window).height());
             if(rate>=0.75) {
                 page++;
                 getJsonandRender(page);
                 lock = false;
             }
        });
    </script>

ajax瀑布流的相关知识点已经讲解完毕,后面会延伸css3的一些属性,若表达有误请指出,望共同进步。

猜你喜欢

转载自blog.csdn.net/gaoyouhuang/article/details/81914573