瀑布流已經是幾乎過時的技術了,不過對于很多想要快速實現它的朋友而言,卻絕非易事,因為即使我們已經有很多現成的代碼,卻發現在自己的開發環境中 無法快速得到自己想要的結果。就像我們現在要介紹的三大利器(masonry+imagesloaded+infinitescroll)即使它們是如此 有效,卻在馬上要使用的時候讓我們拿著如燙手山芋班很難真正達到我們想要的效果。
下面,我們從其原理來講解它們的使用,以幫助你更好的發揮它的功效。但為了快速實現,我們不講解它們的全部內容。
1. 合理的HTML布局是問題的基本
<div id="container"> <div class="item">...</div> <div class="item w2">...</div> <div class="item">...</div> ...</div><div id="page-navi">...</div>
注意:上面的#container和#page-navi被分開,#container的任務就包含瀑布流列表,翻頁的工作交給#page-navi來完成。不少案例中,#container內的結構不規律,有一些雜項,甚至把#page-navi也放在里面,這是導致后面處理中出錯的根源。
2. 存在圖片時masonry+imagesloaded搭配使用
在一些案例里面小白按照官網上給出的代碼進行布局,結構發現圖片重疊在了一起,于是小白慌張了,覺得是不是插件沖突啊,不可能官方代碼也存在問題吧!是的,官方代碼存在問題,因為小白沒有讀完官方的介紹,單純看一小段代碼就會有這個問題。
在圖片出現在.item中時,我們必須等到圖片加載完成再來執行masonry,否則masonry會按照圖片還沒加載的高度來給.item賦予高度,這結果可想而知,就是錯亂感。
而使用imagesloaded則可以避免這種情況,imagesloaded會檢查#container中的圖片是否加載完成,只有當圖片都加載 完了,才會執行回調中的代碼。所以,如果小白要想在存在圖片的時候實現瀑布流,就必須等到圖片加載完了再來使用masonry。當然,有些人不用 imagesloaded,他們牛皮哄哄的使用window.load,但是這樣的話會等很久很久,假如網速慢,圖片加載了半天沒有加載完,瀑布流就永遠 不會出來。所以,我在使用代碼的時候都是這樣使用的:
$('#container').imagesLoaded( function() { new Masonry( document.getElementById('container'),{itemSelector:'.item'} );});
這種用法非常奇怪,官方說你可以用jQuery的方法啦,可以用
$('#container').masonry({itemSelector:'.item'});
就可以啦但是你要這樣思考,jQuery的$()是即時獲取,一個node加載好就馬上獲取的,這可不是什么好事,就像ready和load一樣有的時候ready好了,但是還沒有load,這就是圖片的情況!圖片ready就是加載一個<img>標簽,秒秒鐘的事,但是要load卻要花大把的時間和流量才行。
而如果你的列表中全部都是文字,那么就不用考慮這些了,因為文字真的就是ready可以完成的事。
3.讓infinitescroll執行完,獲得加載完的節點
小白在使用infinitescroll的時候著急的很,希望馬上就能無限拖了,但是有一個非常嚴肅的問題就是,你必須等到要加載的所有的內容都加 載還了,甚至加載過來的圖片也已經搞定了,才開始行動。就像上面那段代碼一樣,如果你加載過來了一堆圖片,但是圖片還沒有load,僅僅是ready好 了,你就開始執行masonry,那么重新加載masonry就會因為從后面一頁抓取的圖片還沒有load,而無法確定.item的高度,最后有可能讓這 些新加載的.item跑到#container的頂部。我想這個情況絕大部分的小白都遇到過。
如果你深刻理解了這里,你就會覺得上面那段短短的,看上去奇怪的代碼,是多么精妙。
把它放在infinitescroll的執行完回調函數中。
$('#container').infinitescroll({ navSelector : '#page-navi', nextSelector : '#page-navi a.next', itemSelector : '#container .item' // .. 省去了其他參數},function(arrayOfNewElems){ $(arrayOfNewElems).appendTo('#container'); $('#container').imagesLoaded( function() { new Masonry( document.getElementById('container'),{itemSelector:'.item'} ); }); // .. 省去了其他動作});
這樣的一個邏輯就非常清晰了。
當然了,在infinitescroll中還有一個this比較難把握。我們雖然獲得了arrayOfNewElems,但是沒有獲取整個DOM。官方提示這個時候this就是獲取的整個DOM,但又馬上提示1.5版本之后this僅僅是獲取的DOM中的#container,讓人有些納悶。
新聞熱點
疑難解答