Nuxt.js + vuetify(+ axios)でページネーションを実装してみる

#はじめに
Nuxt.jsとVuetify, axiosでqiita apiのデータを取得して表示、そしてページネーションを実装し分割していこうと思います。

nuxt.jsについて少し知っている人っていう人に向けた記事です。全く知らないと厳しいと思います。
また自分自身もnuxtが出来るというわけではないので間違っているところがあるかもしれないので、参考程度に見てください。

↓参考サイト
[【vue.js】 Vuetifyで簡単ページネーション(Paginations)
](https://reffect.co.jp/vue/vuetify-simple-pagination)

参考画像
![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573077/67cdd2c9-d8d9-722d-fdb4-34df05ba638e.png)
![スクリーンショット (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573077/30a42673-2360-6abc-2d07-a3355b4461bc.png)

##バージョン
- nuxt 2.0.0
- @nuxtjs/axios 5.3.6
- @nuxtjs/vuetify 1.0.0

##書いていく
```
npx create-nuxt-app <プロジェクトの名前>
```
これで作成しますが、ここでVuetifyとaxiosを選んでおきましょう。

作り終わったら、axiosでqiita apiから取得します。pagesの中にindex.vueに書いていきます。

**まずはscriptタグの中に書きます。**

```javascript:pages/index.vue
export default {
  data(){
    return{
      page: 1,
      length:0,
      lists:[],
      viewLists: [],
      pageSize:10
    }
  },
  async asyncData({ app }) {
    const items = await app.$axios.$get('https://qiita.com/api/v2/items?query=tag:javascript&per_page=30')
    return{
      lists : items
    }
  }
}
```

配列のlistsの中に、qiita apiから受け取ったものをすべて格納するプログラムです。
サーバーサイドで受け取りたいので、asyncdataメソッドを使用します。
asyncDataメソッドの第一引数には**context**を受け取ります。
contextにはapp,route,store,paramsなどなどがあり、appはaxios, vue router, vue storeなどのすべてのプラグインにアクセスすることが出来ます。

$getメソッドではクエリパラメータで、
tag:javascript -> タグがjavascriptであること 
per_page=30 -> 受け取るデータ数が30個
と指定しています。  

またdataについて
pageとはページ番号、1ページ目を押すと1,2ページ目を押すと2となります。
lengthとはページネーションの時に出てくる数字の個数 ページ数を決めます。
listsにはqiita apiから受け取ったものをすべて格納しています。
viewListsには1ページで見ることが出来るものを格納します。
pageSizeでは,1ページで表示できる数を定義しています。

```javascript:pages/index.vue
return {
  lists: items
}
```
ここでlistsにitemsを格納しています。thisでアクセスはできないようです。

**htmlを書いていく**  
  
```html:pages/index.vue
<template>
  <div>
    <ul>
      <li v-for="item in this.viewLists" :key="item.id">
        <div>{{ item.title }}</div>
      </li>
    </ul>
    <v-pagination
      v-model="page"
      :length="length"
      @input = "pageChange"
    ></v-pagination>
  </div>
</template>
```
v-forでthis.viewListsに格納されているものを繰り返して表示させようとしています。

v-pagenationコンポーネントについて
v-modelではpageを参照しています。1ページ(1)を押すとdataの所が1, 2ページ(2)を押すとdataの所が2となります。
:lengthではdataのlengthを参照しています。lengthでページ数を決めます。
inputというeventでは,methodsに定義されているpageChangeイベントを参照しています。

**mountedというライフサイクルで、自動的にページ数を決めたり、どこからどこまでを表示させるか決める**  

```javascript:pages/index.vue
mounted: function(){
    this.length = Math.ceil(this.lists.length/this.pageSize);
    // listsの個数(30)/1ページで見れる数(10) ページ数を決める

    this.viewLists = this.lists.slice(0,this.pageSize);
    //受け取ったすべてのデータが格納されているlistsから、0からthis.pageSize(10)までをthis.viewListsに格納する どこからどこまでを表示するか決める
  },
```
**ページ番号を変えた時に、表示しているデータも変えるイベント**  

```javascript:pages/index.vue
methods:{
    pageChange( pageNumber ){
      this.viewLists = this.lists.slice(this.pageSize * (pageNumber - 1),this.pageSize * (pageNumber))
      // ページ番号2が押された場合　this.lists.slice(10,20) 10から20までを表示
      //最初のページ(1)の場合 this.lists.slice(0,10) 0から10までを表示
    }
}
```
第一引数のpageNumberには押したところのページ番号を受け取ります。ページ番号の3が押された場合、この引数には3が入ります。

**全体のコード**

```javascript:pages/index.vue
<template>
  <div>
    <ul>
      <li v-for="item in this.viewLists" :key="item.id">
        <div>{{ item.title }}</div>
      </li>
    </ul>
    <v-pagination
      v-model="page"
      :length="length"
      @input = "pageChange"
    ></v-pagination>
  </div>
</template>

<script>
export default {
  data(){
    return{
      page: 1,
      length:0,
      lists:[],
      viewLists: [],
      pageSize:10
    }
  },
  mounted: function(){
    this.length = Math.ceil(this.lists.length/this.pageSize);
    this.viewLists = this.lists.slice(0,this.pageSize);
  },
  async asyncData({ app }) {
    const items = await app.$axios.$get('https://qiita.com/api/v2/items?query=tag:javascript&per_page=30')
    return {
      lists : items
    }
  },
  methods:{
    pageChange( pageNumber ){
      this.viewLists = this.lists.slice(this.pageSize * (pageNumber - 1),this.pageSize * (pageNumber))
    }
  }
}
</script>
```

#終わりに
[【vue.js】 Vuetifyで簡単ページネーション(Paginations)
](https://reffect.co.jp/vue/vuetify-simple-pagination)というサイトを参考にしました。
ほんとうにわかりやすい解説なのでおすすめです。

ここまで見てくれてありがとうございました。