前端开发Ajax前端修仙之路

Ajax 实现瀑布流

2019-05-03  本文已影响68人  CondorHero
1.写在前面:

补充个知识点,当我们用 Ajax 来请求 json 数据的时候,类似这样$.get("a.json",function(data){alert(data.result.age);});,会发现如果文件类型是 json 的话,它的 typeof 是 object 类型,可以打点调用自己的 json 里面的数据。但是如果我们请求文件类型是 TXT 或 PHP 等等类型的,类似这样$.get("a.json",function(data){alert(data.result.age);});,虽然文件里面的数据和 json 里面的数据一样,都是:

{
    "data":{
        "age":12
    }
}

但它的 typeof 是 string。这时就不能打点调用 json 里面的数据。必须它转化成 object。转化方法有三种:

var a = "alert(1+2+3)";
eval(a);//结果计算为六

真正的作用是把json由string变为object。

//必须加左右括号,不然浏览器认为{}结束了
var json = eval("(" + data + ")");
console.log(json);
var fun = new Function("return" +data);
fun();
var obj = JSON.parse(data);
alert(obj.result.name);

shim 垫片

2.瀑布流原理

瀑布流原理:
实现的办法主要是使用定位(position)来改变每个小网格 grid 位置。我们要做的是一个三列的瀑布流,只要考虑怎么得到网格的具体位置(top和left值)。
当我们$("#waterfall").append(domstring);使用append的时候,因为grid绝对定位了,所以所有的网格grid会落在一起,这时我们要有序的把他们分开。
我们先去遍历每个网格,得到网格grid后,去不断计算元素上一列的盒子高,把它们累加在一起就是现在这个元素的top值。
至于元素的left值,就是元素index编号求余列数乘以盒子的宽。$(this).index() % 3) * 270

$(".grid").each(function(){
                        var sum = 0;
                        for(var i = $(this).index()-3;i>=0;i-=3){
                            sum += $(".grid").eq(i).outerHeight()+20;
                            console.log(sum);
                        }
                        $(this).css({
                        "top" : sum,
                        "left" : ($(this).index() % 3) * 270
                    });
瀑布流原理
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax实现瀑布流</title>
    <style>
        *{margin:0;padding:0;}
        .waterfall {
            width: 790px;
            margin: 0 auto;
            position: relative;
            background-color: #eabbbb;
        }
        .waterfall .grid img {
            width: 230px;
            border-radius: 10px;
            box-shadow: 2px 2px 3px #333;
        }
        .waterfall .grid {
            width: 230px;
            position: absolute;
            border-radius: 8px;
            box-shadow: 0 5px 10px 0 rgba(0,0,0,0.1);
        }
        .waterfall .grid p {
            overflow: hidden;
            padding: 0 10px;
        }
        .waterfall .grid .title {
            line-height: 25px;
            font-size: 14px;
            float: left;
        }
        .waterfall .grid .author {
            line-height: 25px;
            font-size: 14px;
            float: right;
        }
        .waterfall .grid .content {
            line-height: 25px;
            color: #93999f;
            font-size: 12px;
        }
    </style>
</head>
<body>
    <!--  引包 -->
    <script src="js/jquery-1.12.3.min.js"></script>
    <script src="js/underscore.js"></script>
    <!-- HTML结构的搭建 -->
    <div class="waterfall" id="waterfall">
        <!-- 此处放入模板template -->
    </div>
    <!-- 模板使用underscore的template函数读取json填入数据 -->
    <script type="text/template" id="telt">
        <div id ="test" class="grid">
            <img src="<%=imgurl%>" alt="">
            <p>
                <span class="title"><%=title%></span>
                <span class="author"><%=author%></span>
            </p>
            <p class="content"><%=content%></p>
        </div>
    </script>
    <script>
        <!-- 得到模板标签 -->
        var templateString = $("#telt").html();
        // 模板绑定解析
        var complieFunction = _.template(templateString);
        // Ajax请求数据
        $.get("json/json1.txt",function(data){
            //请求不是json结尾的文件,类型为string
            console.log(typeof data);

            //转化为object对象
            var data = eval("("+ data +")");
            console.log(typeof data);
            // 使用underscore遍历眼拿到的数据
            _.each(data.news,function(dictionary){
                // 把拿到的json放到模板里
                var domstring = complieFunction(dictionary);
                // 把模板添加到事先准备的地方里
                $("#waterfall").append(domstring);

                //此步没任何作用,就是验证模板template里不能用id,只能用类class。
                //改变网格的背景,没任何作用也不报错。
                $("test").css("background-color","red");
                    
                    $(".grid").each(function(){
                        var sum = 0;
                        for(var i = $(this).index()-3;i>=0;i-=3){
                            sum += $(".grid").eq(i).outerHeight()+20;
                            console.log(sum);
                        }
                        $(this).css({
                        "top" : sum,
                        "left" : ($(this).index() % 3) * 270
                    });
                });
                
            });
        });
    </script>
</body>
</html>

思考:相信大家也看到了,最后结尾的时候三列因为小网格的长短不一,但是编号位置是固定的,导致长的太长短的太短。接下来,我们考虑怎么让后面尽量平齐,对齐的方法不在采用固定式的位置填充,采用谁的位置空白离浏览器上端最短,卡片就自动填到谁的列。

3.自动瀑布流
var col_height = [0,0,0];
                // 遍历小格格
                $(".grid").each(function(){
                    //得到数组中最小的那个数
                    var min_value = _.min(col_height);
                    //看一下最短列出现在index几的位置上
                    var min_index = _.indexOf(col_height,min_value);

                    $(this).css({
                        "top" : min_value,
                        "left" : min_index*270
                    });
                    // 更新数字中最小的数,接着进行下次计算
                    col_height[min_index] += $(this).outerHeight()+20;
                });

自动瀑布流
本来数字是678 现在数字786 完全是自适应高度的。

思考:把网速调慢会出现如下现象。

图片折叠现象
增加一个 load方法,等页面的图片全部加载完成在执行下面的函数 。$(window).load(function(){}
$(window).load(function(){
            <!-- 得到模板标签 -->
            var templateString = $("#telt").html();
            // 模板绑定解析
            var complieFunction = _.template(templateString);
            // Ajax请求数据
            $.get("json/json1.txt",function(data){
                //请求不是json结尾的文件,类型为string
                console.log(typeof data);

                //转化为object对象
                var data = eval("("+ data +")");
                console.log(typeof data);
                // 使用underscore遍历眼拿到的数据
                _.each(data.news,function(dictionary){
                    // 把拿到的json放到模板里
                    var domstring = complieFunction(dictionary);
                    // 把模板添加到事先准备的地方里
                    $("#waterfall").append(domstring);
        });

这里补充一个window.onload用法:主要内容如下:

  1. window.onload=function(){}是等待所有的内容都加载完之后执行,比如图片,内容,js,css等。
  2. $(function(){}),是等待DOM加载完之后执行(我的理解是标签绘制完毕之后),图片未加载完时也能执行。
  3. (function(){})是(document).ready(function(){})的简写方式,功能是一样的。
  4. $(window).load(function (){})也是等待所有的内容都加载完之后执行。
  5. 不管是外链js还是页面中的js的window.onload都只执行最后的一个
  6. $(window).load(function (){})可以有多个,而且都是顺序执行。

思考:我在执行过程中确实不会出现图片折叠现象了,但是明显等待刷新时间过长,尤其是把网速调慢之后。怎么减少响应时间?
答:竞速策略

_.each(data.news,function(dictionary){
                        //竞速规则,谁先加载完毕,我先处理谁
                        //这是系统内置构造函数
                        var img = new Image();//可以等于$(document).creatElement("Image");
                        // 让浏览器读到图片
                        img.src = dictionary.imgurl;
                        //用一个数组存储当前三个列的总高度
                        var col_height = [0,0,0];
                        //我们现在给image转为jQuery对象,然后绑定事件
                        $(img).load(function(){
                            //此时这张图片加载完毕了,先处理这个人
                            // 把拿到的json放到模板里
                            var domstring = complieFunction(dictionary);
                            // 把模板添加到事先准备的地方里
                            $("#waterfall").append($(domstring));
                            
                            // 遍历小格格
                            $(".grid").each(function(){
                                //得到数组中最小的那个数
                                var min_value = _.min(col_height);
                                //看一下最短列出现在index几的位置上
                                var min_index = _.indexOf(col_height,min_value);
                                $(this).css({
                                    "top" : min_value,
                                    "left" : min_index*270
                                });
                                // 更新数字中最小的数,接着进行下次计算
                                col_height[min_index] += $(this).outerHeight()+20;
                                // 拿到最大的盒子高,来放进去more盒子
                                $("#waterfall").css("height",_.max(col_height));
                            });
                        });
                });
顺序不一了

修改后完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Ajax实现瀑布流</title>
    <style>
        *{margin:0;padding:0;}
        body {
            background-color: #ccc;
        }
        .waterfall {
            width: 790px;
            margin: 0 auto;
            position: relative;
        }
        .waterfall .grid img {
            width: 230px;
            border-radius: 10px;
        }
        .waterfall .grid {
            padding: 10px;
            width: 230px;
            background-color: white;
            position: absolute;
            border-radius: 8px;
            box-shadow: 1px 5px 10px 0 rgba(0,0,0,0.1);
        }
        .waterfall .grid p {
            overflow: hidden;
            padding: 0 10px;
        }
        .waterfall .grid .title {
            line-height: 25px;
            font-size: 14px;
            float: left;
        }
        .waterfall .grid .author {
            line-height: 25px;
            font-size: 14px;
            float: right;
        }
        .waterfall .grid .content {
            line-height: 25px;
            color: #93999f;
            font-size: 12px;
        }
        .more {
            margin: 0 auto;
            width: 120px;
            color: white;
            background-color: lightblue;
            text-align: center;
            font: 14px/50px "SimSun";
            display: none;
        }
    </style>
</head>
<body>
    <!--  引包 -->
    <script src="js/jquery-1.12.3.min.js"></script>
    <script src="js/underscore.js"></script>
    <!-- HTML结构的搭建 -->
    <div class="waterfall" id="waterfall">
        <!-- 此处放入模板template -->
        
    </div>
    <div class="more">正在加载...</div>
    <!-- 模板使用underscore的template函数读取json填入数据 -->
    <script type="text/template" id="telt">
        <div id ="test" class="grid">
            <img src="<%=imgurl%>" alt="">
            <p>
                <span class="title"><%=title%></span>
                <span class="author"><%=author%></span>
            </p>
            <p class="content"><%=content%></p>
        </div>
    </script>
    <script>
            <!-- 得到模板标签 -->
            var templateString = $("#telt").html();
            // 模板绑定解析
            var complieFunction = _.template(templateString);
            var page = 1;
            getreading(page);
            // Ajax请求数据
            function getreading(page){
                $(".more").show();
                $.get("json/json"+page+".txt",function(data){
                    //请求不是json结尾的文件,类型为string
                    console.log(typeof data);

                    //转化为object对象
                    var data = eval("("+ data +")");
                    // json请求全部完成,没有要请求的了。
                    if(data.news == ""){
                        $(".more").html("没有更多了。。。");
                        return;
                    }
                    console.log(typeof data);
                    // 使用underscore遍历眼拿到的数据
                    _.each(data.news,function(dictionary){
                        var img = new Image();

                        img.src = dictionary.imgurl;
                        //用一个数组存储当前三个列的总高度
                        var col_height = [0,0,0];
                        $(img).load(function(){
                            // 把拿到的json放到模板里
                            var domstring = complieFunction(dictionary);
                            // 把模板添加到事先准备的地方里
                            $("#waterfall").append($(domstring));
                            
                            // 遍历小格格
                            $(".grid").each(function(){
                                //得到数组中最小的那个数
                                var min_value = _.min(col_height);
                                //看一下最短列出现在index几的位置上
                                var min_index = _.indexOf(col_height,min_value);
                                $(this).css({
                                    "top" : min_value,
                                    "left" : min_index*270
                                });
                                // 更新数字中最小的数,接着进行下次计算
                                col_height[min_index] += $(this).outerHeight()+20;
                                // 拿到最大的盒子高,来放进去more盒子
                                $("#waterfall").css("height",_.max(col_height));
                            });
                        });
                
                    // 这个方法不好,体验太差,看着不舒服。
                    //此步没任何作用,就是验证模板template里不能用id,只能用类class。
                    //改变网格的背景,没任何作用也不报错。
                    // $("test").css("background-color","red");

                    //  $(".grid").each(function(){
                    //      var sum = 0;
                    //      for(var i = $(this).index()-3;i>=0;i-=3){
                    //          sum += $(".grid").eq(i).outerHeight()+20;
                    //          console.log(sum);
                    //      }
                    //      $(this).css({
                    //      "top" : sum,
                    //      "left" : ($(this).index() % 3) * 270
                    //  });
                    // });
                    
                    });
                    lock = true;
                    // 加载完成,标签可以消失
                    $(".more").hide();
                });
            }
        var lock = true;
        $(window).scroll(function(){
            var rate = $(window).scrollTop()/($(document).height() - $(window).height());
            if(!lock) return;
            if(rate >=0.7){
                page++;
                lock = false; 
                getreading(page);
            }
        });
    </script>
</body>
</html>
完整实例
上一篇下一篇

猜你喜欢

热点阅读