Ajax 實現(xiàn)瀑布流

一.知識補充:

當我們用 Ajax 來請求數(shù)據(jù)的時候,如果請求的文件是 json 且里面的數(shù)據(jù)也是標準 JSON 格式,類似發(fā)出這樣的請求。

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

這時瀏覽器彈出的內容是 object 。請求的數(shù)據(jù)器類型是對象,這沒什么問題,但是如果我們請求文件類型是 TXT 或 PHP 等等類型的,即使文件里面的內容是標準的 JSON 格式,但是請求文件返回數(shù)據(jù)類型已經(jīng)由 object 改變 為 string 。我們來對比實驗一下。

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

雖然文件里面的數(shù)據(jù)和 a.json 里面的數(shù)據(jù)一樣,都是:

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

這時瀏覽器會彈出 string。這說明如果我們請求的不是 JSON 文件,且文件里面也是標準 JOSN,這時我們就不能打點調用 json 里面的數(shù)據(jù)。必須它轉化成 object。轉化方法有三種:

  • 方法1:eval語句
    eval 語句很神奇,能夠識別字符串,并把字符串當做 JS 語句執(zhí)行。
var a = "alert(1+2+3)";
eval(a);//結果計算為六

真正的作用是把 json 由 string 變?yōu)?object。

//必須加左右括號,不然瀏覽器認為{}結束了
var json = eval("(" + data + ")");
console.log(json);
  • 方法2:new Function()
var fun = new Function("return" +data);
fun();
  • 方法3:JSON.parse()內置函數(shù)
    JSON對象注意,不是一個構造函數(shù),就是一個內置對象。這個對象有兩個方法
    JSON.parse : 字符串 → JSON
    JSON.stringify : JSON → 字符串
var obj = JSON.parse(data);
alert(obj.result.name);
二、.瀑布流原理

瀑布流原理:

實現(xiàn)的辦法主要是使用定位技術(position)來改變每個小網(wǎng)格 grid 位置。我們要做的是一個三列的瀑布流,只要考慮怎么得到網(wǎng)格的具體位置(top 和 left 值)。

當我們$("#waterfall").append(domstring);節(jié)點上樹的時候,因為 grid 絕對定位了,所以所有的網(wǎng)格 grid 會落在一起,這時我們要有序的把他們分開。

我們先去遍歷每個網(wǎng)格,得到網(wǎng)格 grid 后,去不斷計算元素上一列的盒子高,把它們累加在一起就是現(xiàn)在這個元素的top值。

至于元素的 left 值,就是元素 index 編號求余列數(shù)乘以盒子的寬。$(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實現(xiàn)瀑布流</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函數(shù)讀取json填入數(shù)據(jù) -->
    <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請求數(shù)據(jù)
        $.get("json/json1.txt",function(data){
            //請求不是json結尾的文件,類型為string
            console.log(typeof data);

            //轉化為object對象
            var data = eval("("+ data +")");
            console.log(typeof data);
            // 使用underscore遍歷眼拿到的數(shù)據(jù)
            _.each(data.news,function(dictionary){
                // 把拿到的json放到模板里
                var domstring = complieFunction(dictionary);
                // 把模板添加到事先準備的地方里
                $("#waterfall").append(domstring);

                //此步?jīng)]任何作用,就是驗證模板template里不能用id,只能用類class。
                //改變網(wǎng)格的背景,沒任何作用也不報錯。
                $("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>

思考:相信大家也看到了,最后結尾的時候三列因為小網(wǎng)格的長短不一,但是編號位置是固定的,導致長的太長短的太短。接下來,我們考慮怎么讓后面盡量平齊,對齊的方法不在采用固定式的位置填充,采用誰的位置空白(空白處離瀏覽器上端距離最短),卡片就自動填到那個空白的地方。

三.自動瀑布流

為了解決固定位置瀑布流的不雅觀,我們把它變成自動瀑布流。

var col_height = [0,0,0];
// 遍歷小格格
$(".grid").each(function(){
    //得到數(shù)組中最小的那個數(shù)
    var min_value = _.min(col_height);
    //看一下最短列出現(xiàn)在index幾的位置上
    var min_index = _.indexOf(col_height,min_value);

    $(this).css({
        "top" : min_value,
        "left" : min_index*270
    });
    // 更新數(shù)字中最小的數(shù),接著進行下次計算
    col_height[min_index] += $(this).outerHeight()+20;
});

自動瀑布流

本來數(shù)字是678 現(xiàn)在數(shù)字786 完全是自適應高度的。

思考:把網(wǎng)速調慢會出現(xiàn)如下現(xiàn)象。

圖片折疊現(xiàn)象

增加一個 load方法,等頁面的圖片全部加載完成在執(zhí)行下面的函數(shù) 。$(window).load(function(){}

$(window).load(function(){
            <!-- 得到模板標簽 -->
            var templateString = $("#telt").html();
            // 模板綁定解析
            var complieFunction = _.template(templateString);
            // Ajax請求數(shù)據(jù)
            $.get("json/json1.txt",function(data){
                //請求不是json結尾的文件,類型為string
                console.log(typeof data);

                //轉化為object對象
                var data = eval("("+ data +")");
                console.log(typeof data);
                // 使用underscore遍歷眼拿到的數(shù)據(jù)
                _.each(data.news,function(dictionary){
                    // 把拿到的json放到模板里
                    var domstring = complieFunction(dictionary);
                    // 把模板添加到事先準備的地方里
                    $("#waterfall").append(domstring);
        });

這里補充一個window.onload用法:主要內容如下:

  1. window.onload=function(){}是等待所有的內容都加載完之后執(zhí)行,比如圖片,內容,js,css等。
  2. $(function(){}),是等待DOM加載完之后執(zhí)行(我的理解是標簽繪制完畢之后),圖片未加載完時也能執(zhí)行。
  3. (function(){})是(document).ready(function(){})的簡寫方式,功能是一樣的。
  4. $(window).load(function (){})也是等待所有的內容都加載完之后執(zhí)行。
  5. 不管是外鏈js還是頁面中的js的window.onload都只執(zhí)行最后的一個
  6. $(window).load(function (){})可以有多個,而且都是順序執(zhí)行。

思考:我在執(zhí)行過程中確實不會出現(xiàn)圖片折疊現(xiàn)象了,但是明顯等待刷新時間過長,尤其是把網(wǎng)速調慢之后。怎么減少響應時間?
答:競速策略

_.each(data.news,function(dictionary){
    //競速規(guī)則,誰先加載完畢,我先處理誰
    //這是系統(tǒng)內置構造函數(shù)
    var img = new Image();//可以等于$(document).creatElement("Image");
    // 讓瀏覽器讀到圖片
    img.src = dictionary.imgurl;
    //用一個數(shù)組存儲當前三個列的總高度
    var col_height = [0,0,0];
    //我們現(xiàn)在給image轉為jQuery對象,然后綁定事件
    $(img).load(function(){
        //此時這張圖片加載完畢了,先處理這個人
        // 把拿到的json放到模板里
        var domstring = complieFunction(dictionary);
        // 把模板添加到事先準備的地方里
        $("#waterfall").append($(domstring));
        
        // 遍歷小格格
        $(".grid").each(function(){
            //得到數(shù)組中最小的那個數(shù)
            var min_value = _.min(col_height);
            //看一下最短列出現(xiàn)在index幾的位置上
            var min_index = _.indexOf(col_height,min_value);
            $(this).css({
                "top" : min_value,
                "left" : min_index*270
            });
            // 更新數(shù)字中最小的數(shù),接著進行下次計算
            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實現(xiàn)瀑布流</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函數(shù)讀取json填入數(shù)據(jù) -->
    <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請求數(shù)據(jù)
            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遍歷眼拿到的數(shù)據(jù)
                    _.each(data.news,function(dictionary){
                        var img = new Image();

                        img.src = dictionary.imgurl;
                        //用一個數(shù)組存儲當前三個列的總高度
                        var col_height = [0,0,0];
                        $(img).load(function(){
                            // 把拿到的json放到模板里
                            var domstring = complieFunction(dictionary);
                            // 把模板添加到事先準備的地方里
                            $("#waterfall").append($(domstring));
                            
                            // 遍歷小格格
                            $(".grid").each(function(){
                                //得到數(shù)組中最小的那個數(shù)
                                var min_value = _.min(col_height);
                                //看一下最短列出現(xiàn)在index幾的位置上
                                var min_index = _.indexOf(col_height,min_value);
                                $(this).css({
                                    "top" : min_value,
                                    "left" : min_index*270
                                });
                                // 更新數(shù)字中最小的數(shù),接著進行下次計算
                                col_height[min_index] += $(this).outerHeight()+20;
                                // 拿到最大的盒子高,來放進去more盒子
                                $("#waterfall").css("height",_.max(col_height));
                            });
                        });
                
                    // 這個方法不好,體驗太差,看著不舒服。
                    //此步?jīng)]任何作用,就是驗證模板template里不能用id,只能用類class。
                    //改變網(wǎng)格的背景,沒任何作用也不報錯。
                    // $("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>
完整實例
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容