一.知識補充:
當我們用 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)象。

增加一個 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用法:主要內容如下:
- window.onload=function(){}是等待所有的內容都加載完之后執(zhí)行,比如圖片,內容,js,css等。
- $(function(){}),是等待DOM加載完之后執(zhí)行(我的理解是標簽繪制完畢之后),圖片未加載完時也能執(zhí)行。
(document).ready(function(){})的簡寫方式,功能是一樣的。
- $(window).load(function (){})也是等待所有的內容都加載完之后執(zhí)行。
- 不管是外鏈js還是頁面中的js的window.onload都只執(zhí)行最后的一個
- $(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>
