文章

分页组件 Pagy 的页面自动加载

分页组件 Pagy 的页面自动加载

Pagy 号称比 WillPaginate 和 Kaminari 还要快,并节省内存。于是,我在新的 Rails 项目中,将分页模块更换为了 Pagy。

本文主要介绍使用 Pagy 分页时的页面自动加载,比如:下拉到页面底部时,自动加载新闻条目。

模块准备

1、application_controller.rb

1
2
3
class ApplicationController < ActionController::Base
  include Pagy::Backend
end

2、application_helper.rb

1
2
3
module ApplicationHelper
  include Pagy::Frontend
end

3、pagy.rb

1
2
3
4
5
6
7
8
9
...

require 'pagy/extras/countless'
require 'pagy/extras/support'

Rails.application.config.assets.paths << Pagy.root.join('javascripts')
Pagy::VARS[:items] = 25

....

控制器

以 topics_controller 的 index action 为例,这个 action 主要返回新闻条目。

topics_controller.rb

修改数据记录返回方式,使用 pagy_countless:

1
2
3
4
5
6
7
  def index
    ...

    @pagy, @topics = pagy_countless(Topic.where(lv1_tag_name: params[:tag]).order(created_at: :desc), link_extra: 'data-remote="true"')
    
    ...
  end

视图

修改 index.html.erb,数据主显示 div:

由:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="container">
  <div class="list-group col-md-12 col-xs-12">
    <% @topics.each do |topic| %>
    <a href="<%= topic.url %>" target="_blank" class="list-group-item list-group-item-action flex-column align-items-start">
      <div class="d-flex w-100 justify-content-between">
        <h5 class="mb-1"><%= topic.title %></h5>
        <small><%= time_ago_in_words(topic.created_at)%>前,<%= topic.site.title %></small>
      </div>
    </a>
    <% end %>
  </div>
  <div>
    <%== pagy_bootstrap_combo_nav_js(@pagy) %>
  </div>
</div>

变更为:

1
2
3
4
5
6
7
8
9
<div class="container">
  <div class="list-group col-md-12 col-xs-12" id="records_table">
    <%= render partial: 'page_items' %>
  </div>
  <br>
  <div id="div_next_link">
    <%= render partial: 'next_link' %>
  </div>
</div>

增加脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script>
  var loadNextPage = function(){
    if ($('#next_link').data("loading")){ return }  // prevent multiple loading
    var wBottom  = $(window).scrollTop() + $(window).height();
    var elBottom = $('#records_table').offset().top + $('#records_table').height();
    if (wBottom > elBottom){
      $('#next_link')[0].click();
      $('#next_link').data("loading", true);
    }
  };

  window.addEventListener('resize', loadNextPage);
  window.addEventListener('scroll', loadNextPage);
  window.addEventListener('load',   loadNextPage);
</script>

增加关联文件

page_items.html.erb(数据条目):

1
2
3
4
5
6
7
8
<% @topics.each do |topic| %>
<a href="<%= topic.url %>" target="_blank" class="list-group-item list-group-item-action flex-column align-items-start">
  <div class="d-flex w-100 justify-content-between">
    <h5 style="float:left; width:90%"><%= topic.title %></h5>
    <small><%= time_ago_in_words(topic.created_at)%>前,<%= topic.site.title %></small>
  </div>
</a>
<% end %>

next_link.html.erb(下一页):

1
<%== pagy_next_link(@pagy, '', 'id="next_link" style="display: none; text-align: center"') %>

index.js.html(js 返回数据):

1
2
$('#records_table').append("<%= j(render 'page_items')%>");
$('#div_next_link').html("<%= j(render 'next_link') %>");

至此,重启 Rails 项目,看一下页面是不是已经按照想象中进招了呢?

本文由作者按照 CC BY 4.0 进行授权