瀑布流布局的開(kāi)發(fā)實(shí)踐

2013-5-14   

轉(zhuǎn)載藍(lán)藍(lán)設(shè)計(jì)(   m.bouu.cn  )是一家專注而深入的設(shè)計(jì)機(jī)構(gòu) ,為期望卓越的國(guó)內(nèi)外企業(yè)提供有效的   BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、  ipad界面設(shè)計(jì)   、  包裝設(shè)計(jì) 、  圖標(biāo)定制 、  用戶體驗(yàn) 、交互設(shè)計(jì)、   網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)

來(lái)源:http://www.woshipm.com/design/24999.html

360圖片搜索的美女秀場(chǎng)

瀑布流的布局方式展現(xiàn)的內(nèi)容通常是扁平化、瑣碎的東西。首先吸引人的應(yīng)該是圖片,并且圖片是那種參差不齊的,如果瀑布流中文字過(guò)多,會(huì)給人很雜亂的感覺(jué),所以瀑布流更適合單純的圖片瀏覽。

前不久360公司上線的項(xiàng)目–360圖片搜索的美女秀場(chǎng)頻道,就用到了瀑布流的布局方式,這種純粹的看美女圖片的頁(yè)面用瀑布流還是挺合適的。

以前并未開(kāi)發(fā)過(guò)瀑布流布局的網(wǎng)站,第一個(gè)想到的實(shí)現(xiàn)方式就是多列浮動(dòng),從表面上看這種方式要簡(jiǎn)單。

傳統(tǒng)的定位布局方式

但是,目前主流的瀑布流布局都是采用定位的方式,對(duì)每個(gè)單元格計(jì)算定位值,如下圖:

定位方式實(shí)現(xiàn)的瀑布流布局

定位的方式實(shí)現(xiàn)起來(lái)其實(shí)也簡(jiǎn)單,在窗口 resize 時(shí),也可以方便的對(duì)單元格進(jìn)行重新計(jì)算排序。但是計(jì)算的頻率比較高,如果要做無(wú)限的加載數(shù)據(jù),以及 resize 時(shí)的自適應(yīng)排列,那么性能就是一個(gè)必須要重視的問(wèn)題。

如果沒(méi)有任何優(yōu)化手段,成百上千個(gè)單元格本身就很耗資源,resize 時(shí)再全部重新計(jì)算一遍,可以想象瀏覽器在這個(gè)時(shí)候一定很吃力,必然會(huì)有瀏覽器假死的情況。

多列浮動(dòng)的布局方式

再來(lái)看看多列浮動(dòng)布局的實(shí)現(xiàn)方式,多個(gè)單元格組成一列,無(wú)需對(duì)單個(gè)的單元格進(jìn)行定位的計(jì)算,然后對(duì)整列進(jìn)行浮動(dòng),如下圖:

多列浮動(dòng)方式實(shí)現(xiàn)的瀑布流布局

當(dāng)然,這種布局方式在無(wú)限加載和 resize 時(shí)的自適應(yīng)面前,面對(duì)著同樣的問(wèn)題。

自適應(yīng)窗口

先說(shuō) resize 時(shí)的布局自適應(yīng),雖然浮動(dòng)布局的計(jì)算沒(méi)有定位那么方便,但要實(shí)現(xiàn)自適應(yīng)的布局還是可以的。比如原來(lái)有 4 列,resize 時(shí)頁(yè)面寬度變小了,只能放 3 列了,單元格的總數(shù)是不變的,數(shù)據(jù)的順序也是固定的,那么只有把原來(lái) 4 列里面的單元格全部清空,按照數(shù)據(jù)的順序重新計(jì)算排序,依次添加到 3 列中。需要注意的是清空的時(shí)候并不是把單元格的 DOM 元素給刪除掉,而是從 DOM 樹(shù)提取出來(lái)存放在一個(gè)文檔碎片中,這樣就避免了每次都要去創(chuàng)建單元格的 DOM 元素,節(jié)省了創(chuàng)建時(shí)的性能開(kāi)銷,說(shuō)得通俗點(diǎn)就是離線操作。

無(wú)限加載的挑戰(zhàn)

瀏覽器中運(yùn)行的 WEB 程序并不能像桌面軟件那樣會(huì)有足夠多的 CPU 和內(nèi)存去使用。當(dāng)網(wǎng)頁(yè)中的 DOM 元素的數(shù)量呈指數(shù)倍的增長(zhǎng),那么其占用的內(nèi)存也勢(shì)必會(huì)成正比的增長(zhǎng),每個(gè) DOM 元素都會(huì)有性能開(kāi)銷,只是通常情況下 DOM 的數(shù)量并沒(méi)有達(dá)到需要注意型性能的那個(gè)闕值。

無(wú)限加載的瀑布流就必須要注意這種由于 DOM 數(shù)量龐大而引發(fā)出來(lái)的性能問(wèn)題。不能抱著僥幸的心理去認(rèn)為用戶可能滾動(dòng)不了多長(zhǎng)就會(huì)跳出。此次做的瀑布流布局的項(xiàng)目壓根就沒(méi)有內(nèi)頁(yè),都是浮層直接展示大 圖,雖說(shuō)在一定程度上方便了用戶,但同時(shí)也給瀏覽器端很大的性能壓力。用戶如果不需要跳轉(zhuǎn)一直停留在瀑布流的列表頁(yè),只要不關(guān)閉這個(gè)頁(yè)面,內(nèi)存就會(huì)一直沒(méi) 有釋放的機(jī)會(huì)。

雖然頁(yè)面可以無(wú)限長(zhǎng),但是用戶的顯示器的可視區(qū)域是有限的,就好比一個(gè)再富有的人,他晚上睡覺(jué)時(shí)占的面積還是那么大,床的面積也是有限的。由于可視 區(qū)域是有限的,通常會(huì)利用這一點(diǎn)對(duì)沒(méi)加載的 DOM 元素作延遲加載,那么反過(guò)來(lái),能否對(duì)已加載的但不在可視區(qū)域的 DOM 元素做文章呢?答案是肯定的,人有多大膽,地有多大產(chǎn)嘛。

當(dāng)頁(yè)面向下滾動(dòng)的時(shí)候,瀑布流會(huì)創(chuàng)建新的單元格,老的單元格就會(huì)隨著頁(yè)面的向下滾動(dòng)而處于非可視范圍,既然都不可見(jiàn)了,那么為了節(jié)省性能完全可以把 這些老單元格刪除掉。當(dāng)然,也要有技巧性的去刪除。如果頁(yè)面往上滾,滾回去的時(shí)候你總不能給用戶看白板,不能這樣坑人。那么原來(lái)刪除的還得保持原位置加回 去。不悠著點(diǎn)的話,光是這樣一刪一加的兩個(gè)動(dòng)作就夠?yàn)g覽器受的了。作為 WEB 開(kāi)發(fā)者,要時(shí)刻都有瀏覽器是很脆弱的如芒在背的心理。

分組操作

上面說(shuō)到的有技巧性的刪除就是將那些處于非可視區(qū)域的 DOM 元素從 DOM 樹(shù)中提取出來(lái),存儲(chǔ)在一個(gè)文檔碎片的容器中。DOM 元素脫離了 DOM 樹(shù)也會(huì)大大節(jié)省性能的開(kāi)銷,這樣就達(dá)到了節(jié)省性能的目的。當(dāng)然如果僅僅只做到這一步還不太好意思說(shuō)是技巧。正是因?yàn)檫@個(gè),我將 HTML 結(jié)構(gòu)再包裹一層,在 ul 外面添加了一個(gè)div ,稱之為一組,其真實(shí)結(jié)構(gòu)如下圖所示。

在這里,組是比列更大的單位,一組可以是可視區(qū)域大小的尺寸( 目前組還沒(méi)到針對(duì)不同的分辨率 ),一組里面就是浮動(dòng)的自適應(yīng)屏幕分辨率的幾列,每列里面就是一個(gè)個(gè)的單元格。如上圖,這樣幾列就可以組成一組。有了組就可以比較方便的將頻繁出入于 DOM 樹(shù)中的 DOM 元素的性能開(kāi)銷平衡的分配到每一組。可以在頁(yè)面滾動(dòng)向下到指定的位置,只刪除某一組,繼續(xù)向下滾再繼續(xù)刪除。每次都刪除處于最頂端的那一組,因?yàn)槭窃诜强?視區(qū)域內(nèi),用戶也不會(huì)知道你的刪除操作。

頁(yè)面的高度是由一個(gè)個(gè)單元格給撐起來(lái)的,刪除了單元格后,其高度就會(huì)出現(xiàn)變化,由此就會(huì)導(dǎo)致頁(yè)面的高度也跟著變化。在刪除前計(jì)算出組元素的高度,然后設(shè)置其 visibility 為 hidden,讓其在刪除后還保留組元素原有的位置和高度,這樣就不會(huì)有高度的變化了。

通過(guò)的刪除非可視區(qū)域的 DOM 元素的優(yōu)化方法,可以讓頁(yè)面始終保持1-2組單元格,只要你組內(nèi)的單元格的數(shù)量能把握好。這樣就在一定程度上大大的緩解了了頁(yè)面中由于 DOM 數(shù)量過(guò)多而出現(xiàn)的性能開(kāi)銷的問(wèn)題。

當(dāng)窗口 resize 達(dá)到重新排序的寬度條件時(shí),還是要將頁(yè)面中所有單元格重新計(jì)算排序。由于非可視區(qū)域的單元格已經(jīng)不在 DOM 樹(shù)中,那么其計(jì)算也沒(méi)什么壓力了。那些存儲(chǔ)在文檔碎片容器中的單元格也還是需要計(jì)算的,因?yàn)槿绻藭r(shí)頁(yè)面往上滾動(dòng)時(shí)那些離線的單元格還要重新和用戶見(jiàn)面 嘛,只是這個(gè)計(jì)算并不是在 DOM 樹(shù)中而已。

日歷

鏈接

個(gè)人資料

存檔