Vue.jsでpagerを実装

Vue.jsで「[vuejs-paginate](https://www.npmjs.com/package/vuejs-paginate)」を使ってpagerを実装したので、その手順を書きたいと思います。
下記の手順で実装しました。

1. 「vuejs-paginate」をinstall
2. paginate componentに設定
3. Listの番号をstoreで管理して、Listに表示するデータを設定

## 「vuejs-paginate」をinstall

``` terminal
$ yarn add vuejs-paginate
```

## paginate componentに設定

「vuejs-paginate」をinstallしたので、[公式サイト](https://www.npmjs.com/package/vuejs-paginate)を元に「Pagination.vue」に設定していきます。

``` javascript:Pagination.vue

<template>
  <paginate
    v-model="page"
    :page-count="20"
    :page-range="3"
    :margin-pages="2"
    :click-handler="clickCallback"
    :prev-text="'Prev'"
    :next-text="'Next'"
    :container-class="'pagination'"
    :page-class="'page-item'">
  </paginate>
</template>

<script>
import Vue from 'vue';
import Paginate from 'vuejs-paginate';
Vue.component('paginate', Paginate);
</script>
```

## Listの番号をstoreで管理して、Listに表示するデータを設定

### 考えたこと

ここまではpackageの公式サイトを見ればそのまんまなので苦労しないですが、ここから実際にpagerの番号とListに表示するデータを連動させないといけないので改修が必要になります。

で、僕がこの「pagerの番号」をstoreで管理しました。
なぜならその番号がListに表示するデータに関係していて、且つそれらはcomponentで分かれていたのでそれをstoreで横断したいなと思ったので。

### コード

まずはVuexでstoreを読み込んでインスタンスしたものを```#app```で読み込ませます。

``` javascript:main.js
import Vue from 'vue';
import Vuex from 'vuex';
import _store from './store';

Vue.use(Vuex);

const store = new Vuex.Store(_store);

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>',
  store,
});
```

``` javascript:store.js
const state = {
  paginationNUmber: 1, // pagerの番号です。デフォルトを設定
};
```

次に先ほど設定した``` Pagination.vue```を改修します

``` javascript:Pagination.vue
<template>
  <paginate
    v-model="page"
    :page-count="paginationNumber" // pagerの数
    :page-range="20" // 1ページに表示するListの数
    :margin-pages="0"
    :prev-text=null
    :next-text=null
    :click-handler="clickCallback"
    :container-class="'pagination'"
    :page-class="'page-item'">
  </paginate>
</template>

<script>
import Vue from 'vue';
import Paginate from 'vuejs-paginate';

Vue.component('paginate', Paginate);

export default {
  data() {
    return {
      length: 20, // 1ページに表示するListの数
      page: this.$store.state.paginationNUmber, // storeからpage番号を取得
    };
  },
  methods: {
    clickCallback(pageNum) {
      this.page = pageNum; // pageNumはpagerの何番目をclickしたかを取得
      this.$store.state.paginationNUmber = pageNum; // 何番目をclickしたかをstoreの値にset
    },
  },
  computed: {
    paginationNumber() {
      return this.$store.state.hoge.length / 20; // pagerの数を設定するために全データの数を20で割っている
    },
  },
};
</script>
```

次にListを実装するため```$store.state.paginationNUmber```を取得してデータを表示する。

``` javascript:hoge.vue
<template>
  <div>
    <list
      :hoge="sharedState.hoge" // listの全データ
      :start="listStart"
      :count="length"
    >
    </work-list>
    <pagination></pagination>
  </div>
</template>

<script>
import List from '../components/List';
import Pagination from '../components/Pagination';

export default {
  data() {
    return {
      length: 20,
    };
  },
  computed: {
    sharedState() {
      return this.$store.state;
    },
    listStart() {
      return 20 * (this.$store.state.paginationNUmber - 1); // 表示したいデータの最初の値。0、20、40...
    },
  },
  components: {
    List,
    Pagination,
  },
};
</script>
```

``` javascript:List.vie
<template>
  <div>
    <ul>
      <item
        v-for="(item, index) in filtered" :key="index"
        :hoge="hoge"
      >
    </ul>
  </div>
</template>

<script>
import Item from './Item';

export default {
  props: {
    hoge: Array, // listの全データ
    start: Number,
    count: Number,
  },
  computed: {
    filtered() {
      let list = this.hoge.concat();
      if (this.count) {
        list = list.splice(this.start, this.count); //　表示したデータを取得。1〜２０、21〜40、41〜60...の20ごとのデータを取得
      }
      return list;
    },
  },
  components: {
    Item,
  },
};
</script>
```

実際のコードから割愛していますがこのようなコードで実装してみました。
合っていますでしょうか？

### 実装後のview

![01.jpg](https://qiita-image-store.s3.amazonaws.com/0/132855/afb83361-e3fe-7447-81f5-9438f84a6dec.jpeg)


## 参考サイト

- [vuejs-paginate](https://www.npmjs.com/package/vuejs-paginate)
- [これから始めるVue.js 2.0](https://app.codegrid.net/series/2016-vue)