【RailsAPI+Vue.js】Pagy를 이용한 페이지네이션 구현
소개
RailsAPI와 Vuetify로 페이지 네이션을 만들었습니다.
gem을 어느 쪽으로 할까 조사해 보았는데, Pagy가 부드럽게 심플! 가벼운! 라고 하는 것 같기 때문에, Pagy를 사용했습니다.
환경, 사용 기술
Vuetify는 다른 것들도 대체 가능할 것이라고 생각합니다.
Rails 측
Pagy 초기 설정
How To | Pagy 에 쓰여진 거리입니다.
Gemfile
gem 'pagy', '~> 3.5'
매번 익숙한
$ bundle install
를 실행하고 config/initializers/pagy.rb
에 설정 파일을 만듭니다.템플릿 을 복사하여 필요한 곳만 주석 처리를 제거합니다.
config/initializers/pagy.rb
Pagy::VARS[:items] = 3 # 1ページに3件取得する
컨트롤러
app/controllers/api/v1/tweets_controller.rb
class Api::V1::UsersController < Api::V1::BaseController
+ include Pagy::Backend
def index
- users = User.all
+ pagy, users = pagy(User.all)
render json: users
end
end
Postman에서 API를 두드려 응답을 확인해 보겠습니다.
이와 같이, user의 데이터가 3건씩 취득되고 있었습니다(시리얼라이저를 사용하고 있으므로, 컬럼명이 캬멜 케이스가 되고 있습니다).
그러나 이것만으로는 현재 페이지와 총 페이지 수를 알 수 없습니다. 프론트측의 페이지네이션 컴퍼넌트에서는 그러한 데이터가 필요하므로, 추가로 기술해 갑니다.
헤더에 페이지 정보 넣기
app/controllers/api/v1/tweets_controller.rb
+ require 'pagy/extras/headers'
class Api::V1::UsersController < Api::V1::BaseController
include Pagy::Backend
def index
pagy, users = pagy(User.all)
+ pagy_headers_merge(pagy)
render json: users
end
end
인용구 : Headers | Pagy
이 설명은 응답 헤더에 다음 정보를 저장합니다.
KEY
링크
Current-Page
Page-Items
Total-Pages
Total-Count
"Link"의 내용(실제는 일행)↓
<http://127.0.0.1:3000/api/v1/users?page=1>; rel="first",
<http://127.0.0.1:3000/api/v1/users?page=1>; rel="prev",
<http://127.0.0.1:3000/api/v1/users?page=3>; rel="next",
<http://127.0.0.1:3000/api/v1/users?page=3>; rel="last"
이것으로 Rails 측의 처리는 끝입니다.
공통화하는 경우는
after_action
를 사용하는 방법도 있습니다 (see 공식).Vue측
Vue-router는 사용하지 않습니다.
템플릿 부분
Pagination component — Vuetify.js 을 조금 사용자 정의합니다.
<template>
<div class="text-center">
<v-pagination
v-model="currentPage"
:length="page.totalPages"
></v-pagination>
</div>
</template>
<script>
export default {
data () {
return {
requestUrl: "/api/v1/users",
page: {
currentPage: 1,
totalPages: 5,
}
}
},
}
</script>
이제 일단 페이지 네이션을 볼 수는 있었지만 여전히 버튼을 눌러도
page.currentPage
의 값이 변경됩니다.버튼을 누를 때의 동작
컴퍼넌트로부터
@input
이벤트를 받아, changePage
메소드로 처리를 실시합니다.<template>
<div class="text-center">
<v-pagination
v-model="currentPage"
:length="page.totalPages"
+ @input="changePage"
></v-pagination>
</div>
</template>
<script>
export default {
data () {
return {
+ requestUrl: "/api/v1/users",
page: {
currentPage: 1,
totalPages: 5,
}
}
},
+ methods: {
+ changePage(val) {
+ // 処理
+ }
+ }
}
</script>
methods: {
async changePage(val) {
// "/api/v1/users?page=2"などにGETリクエストを送る
const response = await this.$axios.get(`${this.requestUrl}?page=${val}`)
// 受け取ったusersデータを格納する
const { users } = response.data
this.users = users
}
}
페이지 로딩시의 데이터 취득
mounted
에서 첫 번째 화면을 그릴 때의 움직임을 설명합니다.async mounted() {
try {
// "/api/v1/users"にGETリクエストを送る
const response = await this.$axios.get(this.requestUrl)
// それぞれのdataにレスポンスの値を代入する
this.page.totalPages = Number(response.headers["total-pages"])
const { users } = response.data
this.users = users
}
}
최종 코드
<template>
<!-- usersの表示部分。省略 -->
<div class="text-center">
<v-pagination
v-model="page.currentPage"
:length="page.totalPages"
@input="changePage"
/>
</div>
</template>
<script>
import goTo from "vuetify/es5/services/goto" // しれっと追加している
export default {
data() {
return {
requestUrl: "/api/v1/users",
page: {
currentPage: 1,
totalPages: 1,
},
users: []
}
},
async mounted() {
try {
const response = await this.$axios.get(this.requestUrl)
this.page.totalPages = Number(response.headers["total-pages"])
const { users } = response.data
this.users = users
}
},
methods: {
async changePage(val) {
goTo(0) // ページ最上部までスクロール。Vuetifyのメソッド
const res = await this.$axios.get(`${this.requestUrl}?page=${val}`)
const { users } = res.data
this.users = users
}
}
}
</script>
그건 그렇고
추가로 헤더에 정보를 전달하는 경우
다음과 같이 작성하여 추가할 수 있습니다.
requestUrl
를 초기치의 data로 설정하는 것이 어려운 경우는, 이와 같이 헤더에 건네주어 받는 방법도 있습니다. def index
pagy, users = pagy(User.all)
pagy_headers_merge(pagy)
response.headers.merge!({ 'Request-Url' => request.path_info })
render json: users
end
참고 링크
rails API로 페이지 네이션 구현
【vue.js】 Vuetify로 간단 페이지 네이션(Paginations)
Reference
이 문제에 관하여(【RailsAPI+Vue.js】Pagy를 이용한 페이지네이션 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/aiandrox/items/2034a4e90efa3e09b0b4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)