LoginSignup
3
2

More than 3 years have passed since last update.

Vue.jsでページネーションを実装

Last updated at Posted at 2021-02-28

Rails + Vue.jsを使用しています

Vue.js初心者なので分かりにくい説明だと思いますがよろしくお願いします:smiley:

前提条件

APIを使用してJSONでデータを返している前提で書いています
分からない方は以下などを参考にすれば分かると思います
既存のRailsアプリにJSONを返すAPIを実装してみる
Ruby on Rails, Vue.js で始めるモダン WEB アプリケーション入門

実装

vuejs-paginateを使って実装します
準備としてmain.jsに以下を記述

main.js

import Paginate from 'vuejs-paginate'
Vue.component('paginate', Paginate)

まずは全体のコード

完成コード(TweetsPage.vue)

<template>
  <div class="tweets">
    <div v-for="e in getLists" :key="e.id">
      {{e.id}}
      {{e.name}}
    </div>
    <paginate
      :v-model="currentPage" 
      :page-count="getPageCount"
      :click-handler="clickCallback"
      :page-range="3"
      :margin-pages="2"
      :prev-text="'<'"
      :next-text="'>'"
      :container-class="'pagination'"
      :page-link-class="'page-link'">
    </paginate>
  </div>
</template>
<script>
import axios from 'axios'
export default {
  data() {
    return {
      tweets: [],
      currentPage: 1,
      parPage: 10,
    }
  },
  mounted() {
    this.fetchTweets() //fetchTweetsを呼ぶ
  },
  methods: {
    fetchTweets() {
      axios
        .get(`/api/v1/tweets/tweets.json`)
        .then(response =>{
          this.tweets = response.data;
        })
    },
    clickCallback: function (pageNum) {
       this.currentPage = Number(pageNum);
    },
  },
  computed: {
     getLists: function() {
       let current = this.currentPage * this.parPage;
       let start = current - this.parPage;
       return this.tweets.slice(start, current);
     },
     getPageCount: function() {
       return Math.ceil(this.tweets.length / this.parPage);
     }
   }
}
</script>

順番に簡単に解説していきます

まずはdetaの準備

import axios from 'axios'
export default {
  data() {
    return {
      tweets: [], //axiosで取ってきたデータを格納するため
      currentPage: 1, //現在いるページ
      parPage: 10, //1ページで表示するデータ数 今回は1ページにつき10個のデータを表示
    }
  }
  mounted() {
    this.fetchTweets()
  },

axiosというのを使ってJSONで返ってきているデータを取得してtweetsに格納

  methods: {
    fetchTweets() {
      axios
        .get(`/api/v1/tweets/index.json`) //json形式のデータが確認できるURLを記述
        .then(response =>{
          this.tweets = response.data; //dataで定義したtweetsに取ってきたデータを格納
        })
    },

出力したいデータを出力
そしてページネーション実装

<template>
 <div v-for="e in getLists" :key="e.id"> //Railsでいう each doのようなものでしょうか 繰り返しでgetList(この後出てくる)の返り値であるデータを全て表示
   {{e.id}}
   {{e.name}}
 </div>

 <paginate
   :v-model="currentPage" // 現在のページ
   :page-count="getPageCount" 
   :click-handler="clickCallback" //クリック(ページ移動)する度にclickCallbackを呼び出す
   :page-range="3" //3ページ以降は[...]で省力する
   :margin-pages="2" //ラスト2ページから省力しない
   :prev-text="'<'" //戻るボタンは[<]
   :next-text="'>'" //進むボタンは[>]
   :container-class="'pagination'"
   :page-link-class="'page-link'">
 </paginate>
</template>

ページネーションの処理

現在のページを決めたり、今いるページに合ったデータだけを取得したり、全部で何ページ必要か計算したり

  //現在のページを決める処理
    clickCallback: function (pageNum) { 
       this.currentPage = Number(pageNum); //ページネーションで選択したページを現在のページにする 2ページを選択したらcurrentPageに2が代入される 3ページなら3
    },
  },
  computed: {
  //必要なデータだけを取得する処理
     getLists: function() { 
       let current = this.currentPage * this.parPage; //現在のページ×1ページに表示する数
       let start = current - this.parPage;
       return this.tweets.slice(start, current); //そのページに合ったデータだけを表示 1ページ目ならtweetsの0〜9番目を、2ページ目なら10〜19番目のデータを表示
     },
  //総ページ数を決める処理
     getPageCount: function() {
       return Math.ceil(this.tweet.length / this.parPage); //全部で何ページ必要か
     }
   }

後はapplication.html.erbなどにBootstrapのスタイルを適用するCDNを呼び出せば見た目が整います

<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.css">

このようになるのではないでしょうか?
スクリーンショット 2021-03-01 0.40.00.png

おかしな箇所があればコメントください!
最後までご高覧いただきましてありがとうございました!:laughing:

参考記事

「vuejs-paginate」を使ってページネーションを実装する

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2