Ajax 实现瀑布流

作者: CondorHero | 来源:发表于2019-05-03 16:25 被阅读68次
    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。转化方法有三种:

    • 方法1:eval语句
      eval 语句很神奇,能够识别字符串,并把字符串当做JS语句执行。
    var a = "alert(1+2+3)";
    eval(a);//结果计算为六
    

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

    //必须加左右括号,不然浏览器认为{}结束了
    var json = eval("(" + data + ")");
    console.log(json);
    
    • 方法2:new Function()
    var fun = new Function("return" +data);
    fun();
    
    • 方法3:JSON.parse()内置函数
      JSON对象注意,不是一个构造函数,就是一个内置对象。这个对象有两个方法
      JSON.parse : 字符串 → JSON
      JSON.stringify : JSON → 字符串
    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>
    
    完整实例

    相关文章

      网友评论

        本文标题:Ajax 实现瀑布流

        本文链接:https://www.haomeiwen.com/subject/kotinqtx.html