Ajax 实现瀑布流

一.知识补充:

当我们用 Ajax 来请求数据的时候,如果请求的文件是 json 且里面的数据也是标准 JSON 格式,类似发出这样的请求。

$.get("a.json",function(data){alert(typeof data);});

这时浏览器弹出的内容是 object 。请求的数据器类型是对象,这没什么问题,但是如果我们请求文件类型是 TXT 或 PHP 等等类型的,即使文件里面的内容是标准的 JSON 格式,但是请求文件返回数据类型已经由 object 改变 为 string 。我们来对比实验一下。

$.get("a.txt",function(data){alert(typeof data);});

虽然文件里面的数据和 a.json 里面的数据一样,都是:

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

这时浏览器会弹出 string。这说明如果我们请求的不是 JSON 文件,且文件里面也是标准 JOSN,这时我们就不能打点调用 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);
二、.瀑布流原理

瀑布流原理:

实现的办法主要是使用定位技术(position)来改变每个小网格 grid 位置。我们要做的是一个三列的瀑布流,只要考虑怎么得到网格的具体位置(top 和 left 值)。

当我们$("#waterfall").append(domstring);节点上树的时候,因为 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>

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

三.自动瀑布流

为了解决固定位置瀑布流的不雅观,我们把它变成自动瀑布流。

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>
完整实例
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容

  • 瀑布流 瀑布流这个效果以前很流行,常见于图片站,电商站或者艺术类网站 比如最早的蘑菇街,蘑菇街最早的定位模式在于"...
    我拥抱着我的未来阅读 1,120评论 0 4
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,125评论 0 3
  • 前端开发面试题 面试题目: 根据你的等级和职位的变化,入门级到专家级,广度和深度都会有所增加。 题目类型: 理论知...
    怡宝丶阅读 2,572评论 0 7
  • 1.语言基础2.严格模式3.js组成(ECMAScript DOM BOM)4.各种(DOM BOM)例子5.组件...
    蒲公英_前端开发者阅读 1,543评论 0 3
  • @转自GitHub 介绍js的基本数据类型。Undefined、Null、Boolean、Number、Strin...
    YT_Zou阅读 1,145评论 0 0