jquery實現無限滾動瀑布流實現原理


現在類似於pinterest這類的表現效果很火,其實我比較中意的是他的布局效果,而不是那種瀑布流。

雖然我不是特別喜歡這種瀑布流的表現樣式,但是還是寫了幾篇關於無限滾動瀑布流效果的文章,Infinite scroll+Masonry=無限滾動瀑布流infinite-scroll-jquery滾動條(下拉)加載數據插件之類的文章。可能是我表達描述不是很詳細清楚,所以好多朋友看了不是很清楚,並發信給我求解釋。所以有了今天這篇文章。

其實早在:十幾款jquery無限滾動插件這篇文章中我就提到過這種效果的實現原理。主要是判斷滾動條滾動的位置距離底部的距離,如果小於或者等於設置的高度的話,那么就執行ajax加載異步數據到固定的盒子中。我想大家對於這點是比較清楚的,恐怕對於怎樣獲取數據有點不甚了了的感覺。OK,下面看痞子的步步解析!

無限滾動第一步,ajax異步加載的條件:

我們都知道,對於一些列表頁面的布局結構都是一樣的,數據部分是由程序生成的。並且每個頁面都有下一頁的鏈接地址。OK完畢,這點這是基本條件(注意紅色部分)。

為了給大家做直觀的對比,我這里拿出3個頁面進行對比分析,其中采用的masonry的效果,關於這個插件我這里不多說,可以看Masonry-jquery插件打造的瀑布流樣式效果來對該效果有個簡單的認識。這三個頁面的結構是一樣的,內容是不一樣的(我們用不同的圖片來區分)。

這三個頁面左邊都有下一頁的鏈接,鏈接層次分別是

default.html -> default1.html ->default2.html -> 無

下面是三個頁面地址:

http://www.niumowang.org/demo/infinite/default.html
http://www.niumowang.org/demo/infinite/default1.html
http://www.niumowang.org/demo/infinite/default2.html

我們點擊每個頁面的下一頁會看到,頁面會打開一個新的頁面結構與之前的頁面相同,內容不同。最后一個頁面default2.html的下一頁鏈接處是空連接,代表后面沒有頁面了。

無限滾動第二步,ajax異步加載如何進行:

第一步的工作完成后,我們要在上面的下一頁鏈接處做文章。在第一步提供的鏈接中,我們點擊下一頁都會打開下一頁的鏈接,並顯示內容。但是我們現在要做的就是用ajax異步加載數據到當前頁面,實現點擊鏈接不打開新的頁面,但是加載這個鏈接中的數據到本頁面。這里當然就用到了ajax了,所幸jquery封裝的ajax比較簡單,我們很容易實現將其他頁面的內容加載到當前頁面中。

還是三個結構相同,內容不同的頁面:(點擊下一頁可以看到效果)

http://www.niumowang.org/demo/infinite/ajax.html
http://www.niumowang.org/demo/infinite/ajax1.html
http://www.niumowang.org/demo/infinite/ajax2.html

我們來看具體實現代碼部分

$(".next_page a").click(function() {
  //首先取得下一頁的鏈接地址
  var href = $(this).attr("href");
  //判斷該鏈接是否被加載過
  startHref = href;
  //判斷下一頁的鏈接地址是否存在
  if (href != undefined) {
    //如果存在的話,用ajax獲取數據
    $.ajax({
      type: "get",
      url: href,
      success: function(data) {
        //將返回的數據進行處理,挑選出class是post的內容塊
        var $res = $(data).find(".post");
       
        //結合masonry插件,將內容append進ID是content的內容塊中
        $("#content").append($res).masonry('appended', $res);
       
        //newHref獲取返回的內容中的下一頁的鏈接地址
        var newHref = $(data).find(".next_page a").attr("href");
       
        //判斷下一頁地址是否存在,如果存在,替換當前頁的鏈接地址。不存在,將當前頁鏈接地址屬性href移除,並替換內容為“下一頁沒有了”
        if (newHref != undefined) {
          $(".next_page a").attr("href", newHref);
        } else {
          $(".next_page a").html("下一頁沒有了").removeAttr("href")
        }
      }
    })
  }
       
  //返回false,使得點擊進入新頁面失效
  return false;
})

用文字表達一下這個過程就是:點擊鏈接,異步加載這個鏈接中的數據后,挑選出符合條件的內容,然后將內容用js加載到這個頁面固定的容器中,並且將這個鏈接的地址替換成新的鏈接地址。並對如果沒有下一頁的情況進行處理。

其中找到下一頁的鏈接地址可能情況比較多變一些,比如存在“123456…”這樣的鏈接結構;當然這種情況的話,我們可以采用獲取比如class為current的鏈接地址,那么下一頁的地址就是current后面的一個鏈接,然后用返回數據將包含所有分頁地址的容器替換掉。所謂具體問題具體分析,這里點到即止。

另外就是masonry將ajax返回的數據進行重新布局的操作了,這個屬於masonry的范疇,不做過多解釋。關於masonry自己從本站找相關資料。

無限滾動第三步,滾動條控制無限加載:

所謂滾動條控制無限滾動,只不過把點擊的效果替換掉。我們通過滾動鼠標滾輪,或者拖動滾動條到底部來實現原來的點擊異步加載數據的情況。

如果你要實現的話,該怎么做呢?

是的,我們只需要判斷滾動條距離底部的位置就行了。如果到了底部,我們就加載一次數據。
但是還有一個問題,由於我們需要實時獲取滾動條的最新位置,而獲取滾動條位置不是自動的,我們總不能點擊一個按鈕獲取一次數據吧,或者用setTimeout,每隔一段時間獲取一次數據。當然這些都是不可行的。
比較可行的方法就是:我們給(window)窗口綁定一個scroll事件,所謂綁定事件就是監聽這個對象,監視它的一舉一動。如果window窗口滾動的時候,滾動條到底了,那么我們可以進行我們的小動作異步加載數據進來了。OK,看代碼實現。

//首先給窗口綁定事件scroll
$(window).bind("scroll",function() {
    // 然后判斷窗口的滾動條是否接近頁面底部,這里的20可以自定義
    if ($(document).scrollTop() + $(window).height() > $(document).height() - 20) {
          //我這里偷個懶,沒有寫ajax的調用,直接觸發了鏈接的click事件。
          if($(".next_page a").attr('href') != startHref){
                 //這里判斷當前要加載的鏈接是否已經加載過
                 $(".next_page a").trigger("click");
          }
    }
})

演示地址:http://www.niumowang.org/demo/infinite/auto_ajax.html

上面代碼部分,我沒有寫ajax的具體調用過程,而是在原基礎上觸發了鏈接的點擊事件。如果想要看滾動實現的ajax效果的,打開地址:http://www.niumowang.org/demo/infinite/auto_ajax1.html自行查看代碼部分。

上面有個數字是20,就是滾動條距離底部還是20像素的時候開始加載。這里是為了實現預先加載效果,不至於當用戶滾動到底部的時候,數據還沒有加載出來,如果你感覺你的內容較大的話,還可以增加這個值。

無限滾動效果實現原理,總結:

至此一個滾動條實現無限滾動的效果就說完了。做一個最后的總結工作。

可以說目前網上實現無限滾動的效果各有千秋,基於的框架也不盡相同。我寫這篇文章的目的是讓大家領會一種思路,能明白這種效果是怎么做出來的。

我這種方法的文字原理部分:滾動條滾動后,如果到達底部,或者距離底部一段距離的時候,找到下一頁的鏈接地址,獲取這個地址中的數據。然后將返回的數據,采用重新布局添加到固定的容器中。OK,就這么簡單。

無限滾動的高級進階部分:

話說高級進階也沒有多么高級,只不過可能加載數據不是采用這種get或者post,哪怕load頁面的方式,而是通過傳參,從數據庫讀取數據。亦或是增加一些返回數據的特效,比如返回數據后,重新布局的時候增加點動畫,或者滾動條增加點平滑滾動效果。不過爾爾,記住一句話:只要去實踐,一切技術派都是紙老虎。

2013.06.01 BUG調整

下面好幾個朋友提到了多次加載的問題,由於當初設計的時候沒有考慮到加載內容后滾動條變化的問題。所以出現了這個情況。近日有時間解決一下。順便感謝下面提出問題的幾位朋友。
修改方法,主要是定義一個全局變量 var startHref ;
然后next_page觸發一次之后,修改此startHref的值,在滾動的時候拿到當前的next_page中鏈接的值,與startHref進行對比,如果不同的話再執行加載過程。
效果查看:http://www.niumowang.org/demo/infinite/auto_ajax.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM