Masonry + Ajax 实现无限刷新瀑布流

  效果就如我的个人站yooao.cc,把我实现的思路分享给大家。

  Masonry渲染页面如果有图片时需要imagesLoaded辅助,不然有可能会造成布局重叠。

  一个大体的思路:前端取得最后一篇文章的id,下拉时进行Ajax请求添加文章进布局,并同时更新最后一篇文章的id,这样就可往复循环实现无限瀑布流刷新。

  下面说说具体的实现:

一、前端

  对于Masonry  的基本布局,可以看它的文档。

  在页面第一次渲染时,我在容器底部设计一个添加按钮:

<a id="add-button" href="<?php echo Url::to(['post/site/addpost','type_id'=>$type_id,'last_id' => $last_id]) ?>" class="btn btn-danger">加载更多</a>

  因为我用的Yii2框架,所以Yii2提供的方法生成href,生成的href就像这样:http://yooao.cc/index.php?r=post/site/addpost&last_id=71

type_id是对指定类别的文章添加时需要的,last_id就是最后一篇文章的id。

  下面是具体的js代码:

$(function(){

var add_href = $('#add-button').attr('href');
var patt = /\d+$/g;
var last_id = patt.exec(add_href)[0];//取得last_id的值

$('#add-button').hide(); //如果不想显示这个添加按钮,可以将它隐藏
var add_ajax_count = 0;  //定义一个计数器,避免下拉到底时短时间内进行多次Ajax请求
$(window).on('scroll',function(){
     
     //计数器为0并且滚动条离底部小于10px时,才会进行Ajax请求
    if( $(document).scrollTop() + $(window).height() > $(document).height() - 10 && add_ajax_count == 0 ) {
        add_ajax_count++;  //请求一次则将计数器+1
        $.ajax({                 
                type: "post",  
                url: $('#add-button').attr('href'),  
                dataType: "json",  
                async: true,  
                data: {'last_id' : last_id},  //提供给控制器last_id
                beforeSend: function(){                
                $('#ajax-loader').show();        //加载时显示的图片        
                },
                complete: function(){
                $('#ajax-loader').hide();
                },
                success: function (posts) {      
                     

                   var count_post =  posts.length;
              
                    if(count_post == 0 ){
                        return false;
                    }
     //将last_id变更为此次请求的最后一篇文章的id
                    last_id = posts[posts.length-1].id;   
               
               (function(){
                    var i = 0;
    // 这里设置每0.9秒添加一个小块。如果不用计时器而用for,我测试结果是会造成重叠。
                    setInterval(function(){
                    if(i >= count_post){
                        return false;
                    }
                    
                    //$elem是每个小块的模版
                    var $elem = $('<div class="grid-item" >' + posts[i].title + '</div>');    
                           
                    $grid.append($elem);

                    //等图片加载完后才渲染新添加的小块
                    $elem.imagesLoaded( function() {                             
                    $grid.masonry('appended', $elem );               
                    });
                    i++;
                },900); 
            })() 
            
  //8是我设置的每次添加的文章数,如果此次得到的文章数小于8说明已经到最后,count_post 的值将会为1,之后再下拉不会触发Ajax请求。 
            if(count_post < 8 ){
                    return false;
                }else{
                    add_ajax_count--;  
                }
               }                  
        });         
    }
});


});

 

 

 

二、后端

用Yii2举例,控制器代码:

 

   public function actionAddpost($type_id=null)
    {
        $model = new Post();  
        $posts = $model->addPost($type_id);       
        return json_encode($posts);
    
    }

 

 

 

post模型的addPost方法:

 

public function addPost($type_id=null)
    {
        if($_POST['last_id'] !== null){
            $last = $_POST['last_id'];
        }
        if($type_id == null){
            $posts = Post::find()->where('status = 1 AND id < :id',[':id' => $last])->orderBy('id DESC')->limit(POST::PRE_PAGE_POST)->asArray()->all();           
        }else{
            $posts = Post::find()->where('id < :id AND type_id = :type_id AND status = 1',[':id' => $last,':type_id'=>$type_id])->orderBy('id DESC')->limit(POST::PRE_PAGE_POST)->asArray()->all();
             
        }

        return $posts;
    }

 

posted @ 2016-03-06 15:39  aoyo  阅读(6248)  评论(0编辑  收藏  举报