Help us understand the problem. What is going on with this article?

kaminari + jscrollを使った無限スクロールの実装

More than 1 year has passed since last update.

はじめに

Railsで無限スクロールを実装してみたので、その備忘録的に投稿しようと思います。

kaminariというページネーションを簡単に実装できるgemを使い、無限スクロールを実装してみたいと思います。
無限スクロールにはjscrollというjQueryのライブラリを使います。

無限スクロールとは

無限スクロールはメルカリの商品一覧でも見る、下までスクロールすると新しい商品が自動的に読み込まれるあれです。

無限スクロールにはページネーションを先に実装する必要があります。
ページネーションにはkaminariというgemを使います。

Railsのバージョンは5です。

kaminariのインストール

Gemfile
gem 'kaminari'

を記載して、

bundle install

を実行するだけです。

jscrollのインストール

jscrollには現時点では(2019年2月)gemが存在しないと思われますので、公式のページからダウンロードしてきます。

なお、jscrollを使うにはjQueryが必要です。
railsでjQueryを使えるようにするにはこちら

jscroll公式ページ

  • CDNで使えるようにする

手軽に試してみたい人はこちら。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jscroll/2.4.1/jquery.jscroll.min.js"></script>
  • ローカルに落とす

こちらのdistからjquery.jscroll.min.jsをダウンロードしてきます。
jscrollのGithub

そして、asset/javascripts配下にダウンロードしたjquery.jscroll.min.jsを置いて、(読み込めれば場所はどこでも)

assets/javascripts/application.js
//= require jquery.jscroll.min.js

を記載。

ページネーションを実装

今回はDBに登録してあったプログラミング言語を一覧で表示するだけの画面を作っていきたいと思います。

skillsというcontrollerを作成し、以下を記載。

skills_controller.rb
class SkillsController < ApplicationController
  def index
    @skills = Skill.page(params[:page]).per(10)
  end
end

.page(params[:page]).per(10)の部分が一画面に10個の要素を表示するということになります。

そして、index.html.erbに

index.html.erb
<ul class="skill-list jscroll">
  <% @skills.each do |skill| %>
    <li><%= skill.skill_name %></li>
  <% end %>
  <%= paginate @skills %>
</ul>

<%= paginate @skills %>の部分がページの部分。

以上を記載すると、ページネーションが実装できます。とても簡単ですね。
以下のような画面になりました。

pagination.png

無限スクロールを実装

無限スクロールは以下のようにして実装できます。
以下のソースは画面を開いた段階で、次の要素が読み込まれる実装になります。

coffeescript

skills.coffee
$ ->
  $('.jscroll').jscroll
  return

jQuery

$(function() {
  $('.jscroll').jscroll;
});

ただ、これだけだと動きません・・・。次のページへのリンクを指定する必要があるためです。
このようにすると、画面を読み込むと自動的に次のページが読み込まれます。

coffeescript

skills.coffee
$ ->
  $('.jscroll').jscroll
    nextSelector: 'span.next a'
  return

jQuery

$(function() {
  $('.jscroll').jscroll({
    nextSelector: 'span.next a'
  });
});

次のリンクを指定するにはnextSelectorを指定してやります。
ただ、ここれだけでは変な感じで読みこまれると思います。

pagination.png

読み込まれている場所はずれているし、jsのconsoleを見ると、rails-ujsが既に読み込まれていますよ、みたいなエラーが出ていると思います。

これは、次のページのhtmlを全て読み込んでしまっていて、javascriptなども重複して読み込んでしまっているのでエラーが出ています。

なので、次のページの読み込む要素を指定してやって、その要素だけ読み込ませるようにします。

coffeescript

skills.coffee
$ ->
  $('.jscroll').jscroll
    contentSelector: '.skill-list'
    nextSelector: 'span.next:last a'
  return

jQuery

$(function() {
  $('.jscroll').jscroll({
    contentSelector: '.skill-list',
    nextSelector: 'span.next:last a'
  });
});

次にロードする要素として、ulの.skill-listを指定しています。

nextSelectorでspan.next:last aで:lastを指定しているのは、
読み込むリンクはhtmlを読み込んでいくとどんどん増えていきます。

なので、読み込まれた最後のリンクを指定してやることで、どんどん次のページを読み込むようにしています。

ulはpaddingが入ることを忘れていたので、

skills.scss
ul.skill-list {
  padding: 0;
}

を記載。すると、以下のように。
pagination.png

あとはページの部分が邪魔なので、

skills.scss
nav.pagination {
  display: none;
}

でページ部分を表示させないようにする。

最終的な画面

Loadingしている時、
pagination.png

Loading後
pagination.png

後は、画面下までスクロールしたことをjavascriptで検知させて、$('.jscroll').jscrollを呼び出してやれば次の要素を読み込めます。

画面下までスクロールしたことを判定

こちらの記事を参考にさせて頂きました。

coffeescript

$(window).on 'scroll', ->
  scrollHeight = $(document).height()
  scrollPosition = $(window).height() + $(window).scrollTop()
  if (scrollHeight - scrollPosition) / scrollHeight <= 0.05
    # スクロールの位置が下部5%の範囲に来た場合
    $('.jscroll').jscroll
      contentSelector: '.skill-list'
      nextSelector: 'span.next:last a'
    return
  return

jQuery

$(window).on('scroll', function() {
    scrollHeight = $(document).height();
    scrollPosition = $(window).height() + $(window).scrollTop();
    if ( (scrollHeight - scrollPosition) / scrollHeight <= 0.05) {
          $('.jscroll').jscroll({
            contentSelector: '.skill-list',
            nextSelector: 'span.next:last a'
          });
    }
});

これで、画面下までスクロールしたら自動的に、次の要素が読み込まれるようになります。

おわりに

ライブラリなどを使うと非常に簡単に無限スクロールが実装できます。

結構モダンなページがお手軽にできると思いますので、是非お試しあれ。

s_yasunaga
学生時代はJavaをずっと勉強。プライベートではC++やPythonなど色々な言語に手をだす。得意なのは、JavaやDB操作。 仕事ではVB.NETやPHPなどの現場に行かされ、現在は自社内のプロジェクトのためRubyを勉強中。Railsに関する記事を書いてゆくと思います。
http://sh0122.hatenadiary.jp/
assign-navi
株式会社アサインナビは、日本最大級のエンジニア・IT企業とIT案件のマッチングサイト「アサインナビ」を運営する企業です。
https://assign-navi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした