レールと刺激による無限のスクロール・ページネーション
35114 ワード
この記事では、いくつかの行のコードのみを使用して、無限のスクロールページシステムを構築する方法を学びます.我々は非常に単純なレールのアプリケーションを作成し、あなたのアプリケーションのすべてのリソースをPaginateに再利用することができます刺激コントローラで無限スクロール機能を実装します.我々はステップでこのステップを行うので、始めましょう!
Railsアプリケーションの作成
次のようにします.
我々は、第2のステップとして非常に単純なページネーションを加える準備ができています.
無限スクロールのないページネーションの追加
Pageinationのために、我々はBasecamp Teamと呼ばれる非常に単純な宝石を使用しますgeared pagination . それは非常に小さい(私はこの記事を書くときに50未満のコミット)と非常によく書かれています.
宝石を宝石ファイルに加えてインストールしましょう.その後、サーバーを再起動することを忘れないでください!
刺激による無限スクロールページ付けの追加
無限スクロールは次のように動作します. ビューポートが隠しページの次のリンクを横切るたびに、追加の記事を取得するAjaxリクエストをトリガーします その後、リストにそれらの記事を追加し、次のページと現在の次のページのリンクを置き換えます 我々は、最後のページに到達するまで、プロセスを繰り返します! 準備ができましたか.レッツゴー!
まず、刺激を伴うページ付けコントローラを作成し、記事インデックスページに接続しましょう.
を加えましょう
すべてが正しく配線されているので、我々は我々の機能を追加する準備が整いました.まず最初にやることは
どうやってやるの?
JavaScriptオブジェクトを
我々の刺激コントローラにこれを加えましょう:
まず、刺激コントローラが初期化されると、次のページリンクを観察し始める.
どのように、我々は非同期JavaScriptをしますか?非同期/待機して約束!
機能
RailsでAjaxリクエストを行うには、新しいブランドを使用しますrails/request.js 2021年6月に作成された図書館.この図書館はラッパです
パッケージに追加しましょう.糸を使ったJSON :
私たちの無限のスクロールが動作しますが、1つだけの反復のためです!我々はそれを再帰的にする必要がある.たびに新しい記事は、ページに追加され、新しい次のページのリンクも追加されます!我々は、この無限の次のページのリンクを読む無限のスクロールを持つことができるように観察する必要があります!
この再帰を加えましょう!
最終的なコントローラです
最後に、あなたはそれが本当の無限のスクロールを作るためにページ上の次のページのリンクを非表示にすることができますと思う.
宅配と有用資源
rails/request.js フェッチのラッパを提供するライブラリです.Railsアプリケーションで作業するときに、非常に便利です.なぜなら、Railsアプリケーションで必要とされるフードの下にいくつかのヘッダを設定するからです.
basecamp/gearder_pagination は非常に小さなページの宝石(50コミット未満)です.あなたがRuby/Railsでいくつかのトリックを学びたいならば、あなたはコードを読むべきです! JavaScriptの非同期アクションで作業する場合は、約束とasync/waitを使用して動作します.The Intersection Observer API ページ上の他の要素と交差するビューポートに基づいて動作をトリガーするのに役立ちます.
クレジット
この記事は大いに感激しているhey.com 's無限スクロール.Basecampチームのおかげでleaving the source maps open . 私が同様の機能を構築しなければならなかったとき、それは本当に役に立ちました!
この記事は好きでしたか.
あなたが新しい記事を発行するときに通知を得ることができます.私は時々この無限のスクロールのような興味深い機能に取り組んでください!
Railsアプリケーションの作成
次のようにします.
rails new infinite-scroll-article --webpack=stimulus
JavaScriptなしで動作するページ付け機能を構築します.まずモデルを作りましょうArticle
文字列のタイトルとテキストの内容です.rails g model Article title content:text
rails db:migrate
我々が我々を持つ今Article
モデルは、Paginateに私たちのために100の記事を作成する種をつくりましょう.# db/seeds.rb
puts "Remove existing articles"
Article.destroy_all
puts "Create new articles"
100.times do |number|
Article.create!(
title: "Title #{number}",
content: "This is the body of the article number #{number}"
)
end
データベース内の100個の記事を永続化するには、次のコマンドを実行します.rails db:seed
私たちはモデルの部分に行くのが良いです、今では#index
そして、それらの100条を表示するための対応するビュー.rails g controller articles index
ルートファイルで、記事リストをホームページにしましょう.# config/routes.rb
Rails.application.routes.draw do
root "articles#index"
end
コントローラのすべての記事をデータベースから検索します.# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
@articles = Article.all
end
end
最後に、ビュー内のすべての100記事を表示しましょう.<!-- app/views/articles/index.html.erb -->
<h1>Articles#index</h1>
<% @articles.each do |article| %>
<article>
<h2><%= article.title %></h2>
<p><%= article.content %></p>
</article>
<% end %>
これでローカルサーバーを起動できますrails s
とwebpackサーバwebpack-dev-server
そして、我々がちょうど作成した100の記事のリストをホームページで見てください!我々は、第2のステップとして非常に単純なページネーションを加える準備ができています.
無限スクロールのないページネーションの追加
Pageinationのために、我々はBasecamp Teamと呼ばれる非常に単純な宝石を使用しますgeared pagination . それは非常に小さい(私はこの記事を書くときに50未満のコミット)と非常によく書かれています.
宝石を宝石ファイルに加えてインストールしましょう.その後、サーバーを再起動することを忘れないでください!
bundle add geared_pagination
bundle install
宝石を使用すると、非常に簡単です、私たちはset_page_and_extract_portion_from
以下のようなコントローラでのメソッド# app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
def index
# Note that we specify that we want 10 articles per page here with the
# `per_page` option
@articles = set_page_and_extract_portion_from Article.all, per_page: [10]
end
end
ビューでは、ページの末尾にPaginationロジックを追加する必要があります.<!-- app/views/articles/index.html.erb -->
<h1>Articles#index</h1>
<% @articles.each do |article| %>
<article>
<h2><%= article.title %></h2>
<p><%= article.content %></p>
</article>
<% end %>
<% unless @page.last? %>
<%= link_to "Next page", root_path(page: @page.next_param) %>
<% end %>
Pagination作品!次のページリンクをクリックして、ページが変更されます.しかし、それは我々が欲しいものでありません!我々が欲しいものは無限のスクロールです、そして、それはこの記事の最も面白い部分です!刺激による無限スクロールページ付けの追加
無限スクロールは次のように動作します.
まず、刺激を伴うページ付けコントローラを作成し、記事インデックスページに接続しましょう.
を加えましょう
nextPageLink
コントローラが初期化されたときにターゲットをコンソールに記録します.// app/javascript/controllers/pagination_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static targets = ["nextPageLink"]
initialize() {
console.log(this.nextPageLinkTarget)
}
}
それを動作させるには、追加することでHTMLを更新する必要がありますdata-controller="pagination"
記事一覧とdata-pagination-target="nextPageLink"
をクリックします.インデックスコードは次のようになります.<!-- app/views/articles/index.html.erb -->
<div data-controller="pagination">
<% @articles.each do |article| %>
<article>
<h2><%= article.title %></h2>
<p><%= article.content %></p>
</article>
<% end %>
<% unless @page.last? %>
<%= link_to "Next page",
root_path(page: @page.next_param),
data: { pagination_target: "nextPageLink" } %>
<% end %>
</div>
ページを更新し、次のページリンクをコンソールにログインしてください.すべてが正しく配線されているので、我々は我々の機能を追加する準備が整いました.まず最初にやることは
console.log("intersection")
ビューポートが次のページリンクと交差するとき.どうやってやるの?
JavaScriptオブジェクトを
IntersecionObserver
! The Intersection Observer API ターゲット要素の祖先要素またはトップレベルドキュメントのビューポートとの交差点の変更を非同期的に観察する方法を提供します.我々の刺激コントローラにこれを加えましょう:
// app/javascript/controllers/pagination_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static targets = ["nextPageLink"]
initialize() {
this.observeNextPageLink()
}
// private
async observeNextPageLink() {
if (!this.hasNextPageLinkTarget) return
await nextIntersection(this.nextPageLinkTarget)
console.log("intersection")
}
}
const nextIntersection = (targetElement) => {
return new Promise(resolve => {
new IntersectionObserver(([element]) => {
if (!element.isIntersecting) {
return
} else {
resolve()
}
}).observe(targetElement)
})
}
すごい!それは機能の最も複雑な部分です!それを壊しましょう.まず、刺激コントローラが初期化されると、次のページリンクを観察し始める.
initialize() {
this.observeNextPageLink()
}
ページの次のページ・リンクがないならば、コントローラは何もしません.しかし、次のページリンクがあるならば、我々は交差点を待ちますconsole.log("intersection")
. このプロセスは非同期であることに注意してください:私たちは、次の交差点が発生する予定がわからない!どのように、我々は非同期JavaScriptをしますか?非同期/待機して約束!
機能
observeNextPageLink
この理由は非同期です.どのように現在の英語のように読むかを参照してください?次のページリンクと次の交差点を待つconsole.log("intersection")
.async observeNextPageLink() {
if (!this.hasNextPageLinkTarget) return
await nextIntersection(this.nextPageLinkTarget)
console.log("intersection")
}
最後にはnextIntersection
関数はPromise
これは次のページリンクがビューポートと交差するときに解決されます.これは簡単に新しいIntersectionObserver
それは次のページリンクを観察するでしょう.const nextIntersection = (targetElement) => {
return new Promise(resolve => {
new IntersectionObserver(([element]) => {
if (!element.isIntersecting) {
return
} else {
resolve()
}
}).observe(targetElement)
})
}
私たちの整備士が適所にあるので、我々は我々の代わりにする必要があるconsole.log("intersection")
何か役に立つ.代わりに、“交差点”のログをコンソールで、我々は次のページから記事を取得し、我々はすでに持っている記事のリストに追加します!RailsでAjaxリクエストを行うには、新しいブランドを使用しますrails/request.js 2021年6月に作成された図書館.この図書館はラッパです
fetch
通常はJavaScriptでAJAXリクエストを行うために使用します.これは、自動的にRailsと統合、例えば、それを自動的に設定しますX-CSRF-Token
Railsアプリケーションで必要とされるヘッダー、これは我々がそれを使用する理由です!パッケージに追加しましょう.糸を使ったJSON :
yarn add @rails/request.js
さあインポートしましょうget
PageGationコントローラの機能と置換console.log("intersection")
実際の論理で.コードは次のようになります.import { Controller } from "stimulus"
import { get } from "@rails/request.js"
export default class extends Controller {
static targets = ["nextPageLink"]
initialize() {
this.observeNextPageLink()
}
async observeNextPageLink() {
if (!this.hasNextPageLinkTarget) return
await nextIntersection(this.nextPageLinkTarget)
this.getNextPage()
}
async getNextPage() {
const response = await get(this.nextPageLinkTarget.href) // AJAX request
const html = await response.text
const doc = new DOMParser().parseFromString(html, "text/html")
const nextPageHTML = doc.querySelector(`[data-controller~=${this.identifier}]`).innerHTML
this.nextPageLinkTarget.outerHTML = nextPageHTML
}
}
const nextIntersection = (targetElement) => {
return new Promise(resolve => {
new IntersectionObserver(([element]) => {
if (!element.isIntersecting) {
return
} else {
resolve()
}
}).observe(targetElement)
})
}
ここで唯一の変更はimport { get } from "@rails/request.js"
これは、我々のサーバーとのために取得AJAX要求を使用するconsole.log("intersection")
それはthis.getNextPage()
. この最後の方法を理解しましょう.async getNextPage() {
const response = await get(this.nextPageLinkTarget.href) // AJAX request
const htmlString = await response.text
const doc = new DOMParser().parseFromString(htmlString, "text/html")
const nextPageHTML = doc.querySelector(`[data-controller=${this.identifier}]`).outerHTML
this.nextPageLinkTarget.outerHTML = nextPageHTML
}
まず、サーバにGETリクエストを発行し、応答を待ち、response
変数.次に、レスポンスからテキストを抽出し、htmlString
変数.このクエリを使用するにはhtmlString
, 最初にHTML文書を作成するために構文解析を行いますDOMParser
. 次に、このドキュメントをdoc
変数.次に、このドキュメントから次のページ記事と次のページリンクを展開し、現在の次のページリンクを置き換えることにより、記事リストに追加します.私たちの無限のスクロールが動作しますが、1つだけの反復のためです!我々はそれを再帰的にする必要がある.たびに新しい記事は、ページに追加され、新しい次のページのリンクも追加されます!我々は、この無限の次のページのリンクを読む無限のスクロールを持つことができるように観察する必要があります!
この再帰を加えましょう!
最終的なコントローラです
import { Controller } from "stimulus"
import { get } from "@rails/request.js"
export default class extends Controller {
static targets = ["nextPageLink"]
initialize() {
this.observeNextPageLink()
}
async observeNextPageLink() {
if (!this.hasNextPageLinkTarget) return
await nextIntersection(this.nextPageLinkTarget)
this.getNextPage()
await delay(500) // Wait for 500 ms
this.observeNextPageLink() // repeat the whole process!
}
async getNextPage() {
const response = await get(this.nextPageLinkTarget.href)
const html = await response.text
const doc = new DOMParser().parseFromString(html, "text/html")
const nextPageHTML = doc.querySelector(`[data-controller~=${this.identifier}]`).innerHTML
this.nextPageLinkTarget.outerHTML = nextPageHTML
}
}
const delay = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
const nextIntersection = (targetElement) => {
// Same as before
}
ここでは、私たちはobserveNextPageLink
関数は、あまりにも高速スクロールを避けるために500 msを待つことによって機能し、我々は、次のページのリンクを観察し、1つは、このように我々はちょうど行った全体のプロセスを繰り返す!最後に、あなたはそれが本当の無限のスクロールを作るためにページ上の次のページのリンクを非表示にすることができますと思う.
<% unless @page.last? %>
<%= link_to "Next page",
root_path(page: @page.next_param),
data: { pagination_target: "nextPageLink" },
style: "visibility: hidden;" %>
<% end %>
あなたはそれをやった、レールと刺激で本当の無限のスクロールを構築!宅配と有用資源
rails/request.js フェッチのラッパを提供するライブラリです.Railsアプリケーションで作業するときに、非常に便利です.なぜなら、Railsアプリケーションで必要とされるフードの下にいくつかのヘッダを設定するからです.
basecamp/gearder_pagination は非常に小さなページの宝石(50コミット未満)です.あなたがRuby/Railsでいくつかのトリックを学びたいならば、あなたはコードを読むべきです!
クレジット
この記事は大いに感激しているhey.com 's無限スクロール.Basecampチームのおかげでleaving the source maps open . 私が同様の機能を構築しなければならなかったとき、それは本当に役に立ちました!
この記事は好きでしたか.
あなたが新しい記事を発行するときに通知を得ることができます.私は時々この無限のスクロールのような興味深い機能に取り組んでください!
Reference
この問題について(レールと刺激による無限のスクロール・ページネーション), 我々は、より多くの情報をここで見つけました https://dev.to/alexandreruban/infinite-scroll-pagination-with-rails-and-stimulus-41npテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol