一.知识补充:
当我们用 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用法:主要内容如下:
- window.onload=function(){}是等待所有的内容都加载完之后执行,比如图片,内容,js,css等。
- $(function(){}),是等待DOM加载完之后执行(我的理解是标签绘制完毕之后),图片未加载完时也能执行。
- (document).ready(function(){})的简写方式,功能是一样的。
- $(window).load(function (){})也是等待所有的内容都加载完之后执行。
- 不管是外链js还是页面中的js的window.onload都只执行最后的一个
- $(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>