牛刀试手之折腾瀑布流
其实很久之前就有朋友问我有没有弄过瀑布流,当时这个东西我知道它的实现后的形式,就是蘑菇街那种啊,然后我又懒得想做,就找了一个网上的实现方式直接给了他了,我连想一下怎样实现都没有想,最后,“报应”来了,百度一面的时候,最后就问到瀑布流的实现了,然后也凸显一大弱点就是缺少必要的实战,细想一下,前端的知识,我都是通过自学的,看书占据课余比较大的时间,实战经验确实少,做重构的居多,没有试过从后台中拿数据,接着展示出整个页面,现在还停留在相对浅的状态。
所以这次我要吸取教训,首先先折腾这个瀑布流,首先,究竟瀑布流是怎样实现的呢?百度一下,发现了挺多的相关网站,挑选了挺多看了一下,这里推荐一下一些感觉挺不错的文字,淘宝UED的瀑布流布局浅析,还有张鑫旭大神的折腾:瀑布流布局(基于多栏列表流体布局实现)。接着就是我的折腾时候了,布局就选择了传统多列浮动,为啥呢?简单嘛。
首先,准备工作,一大堆的图片,一个json文件(仿照从后端拿回的数据)。然后,就想怎样一步一步的实现,先是要多少个参数呢,还有把那几列给生成出来,怎样添加图片呢,怎样检测到滚动条滚到最下呢。
折腾了好一会把代码给敲出来了,由于是新手,轻拍哈。代码有点恶心。
<div class="pubu" id="pubu"> </div>
(function(){ var pubu={ container:"pubu", //包含着整个瀑布流的容器ID columnWidth:239, //每列的宽度 marginR:8, //列与列之间的间隔 loadNum:16, //每次加载多少个 datas:null, //从后台返回到的json数据 colNum:5, //多少列 hasLoadNum:0, //已经加载了多少个数据 totalNum:1000, //总共有多少个,初始值很大,这里设为了1000 createFirst:function(){ //向容器插入列,列是浮动 var contain=document.getElementById(this.container),i, colNum=this.colNum, createNode=document; for(i=0;i<colNum;i++){ var div=createNode.createElement("div"); div.style.width=this.columnWidth+"px"; div.className="list a"+i; if(i<colNum-1) { div.style.marginRight=this.marginR+"px"; } div.style.cssFloat="left"; contain.appendChild(div); } return this; }, callData:function(callback){ //获取数据,这里我用了ajax同步,但是如果数据很大很大的时候,还是用异步最好 var xmlHttp=new XMLHttpRequest(),that=this; //但是这里我不知道应该怎么处理好了。 xmlHttp.onreadystatechange=function(){ if(xmlHttp.readyState===4){ if(xmlHttp.status>=200&&xmlHttp.status<300||xmlHttp.status===304){ var data=JSON.parse(xmlHttp.responseText); callback(data); //使用回调函数 } } } xmlHttp.open("get","pics.php",true); xmlHttp.send(null); }, findShort:function(){ //获取高度最小的那一列 var lists=document.querySelectorAll(".list"),minHeight,k=0; minHeight=lists[0].offsetHeight; for(var i=1,len=lists.length;i<len;i++){ var here=lists[i].offsetHeight; if(minHeight>here){ minHeight=here; k=i; } } return lists[k]; }, insertPic:function(){ //向最短的那一列,插入图片 var div=document.createElement("div"), a=document.createElement("a"), img=document.createElement("img"); this.totalNum=this.datas.length; img.src=this.datas[this.hasLoadNum].url; img.title=this.datas[this.hasLoadNum].name; img.width="230"; this.hasLoadNum++; a.appendChild(img); div.appendChild(a); this.findShort().appendChild(div); }, insertList:function(){ //插入loadNum个图片,最后剩下少于loadNum个图片时作一点处理 var n=this.loadNum; if(this.totalNum-this.hasLoadNum<n){ n=this.totalNum-this.hasLoadNum; } for(var i=0;i<n;i++){ this.insertPic(); } return this; }, insertAll:function(){
var that=this; this.callData(function(data){
that.datas=data;
that.insertList();
}); //获取数据 //加进列里面 return this; }, throttle:function(method,context){ //一个函数节流的函数 clearTimeout(method.tId); method.tId=setTimeout(function(){ method.call(context); },100); }, addEvent:function(){ //当鼠标滚到最下面时,依次加入一定数量的图片 var pubu=this; var method=function(){ var that=document; var buffer=that.documentElement.scrollHeight-that.documentElement.clientHeight; if(window.scrollY===buffer) { pubu.insertList(); } }; document.addEventListener("scroll",function(){ pubu.throttle(method); });return this; } } pubu.createFirst().insertAll().addEvent(); })();
自评:其实这个代码还有很多不足的地方,就如那个ajax部分,一开始为了得到数据,我使用了同步方法,但是这样不符合ajax的特性,后面听了一下别人的建议,我尝试使用回调函数。