beta

Vue3のsetup関数でVue Routerを使ってページネーションを制御する

Vue3で導入されたsetup関数とVue Routerを使うと、ページネーション処理が一括で書けるようになるので、試してみました。

公開日:2022年4月12日

setup関数を使うとまとめてページネーション処理ができる

Vue3から導入されたsetup関数とComposition APIを使うと、Vue Routerでのページネーション処理はsetup関数内で一括定義できます。

やっている処理自体はVue2時代とほとんど同じですが、「何で発火して、どこで処理をしているのか」が明確になるのは、サイトを構築する上でメリットと感じました。

ページング処理をしてみる

一覧ページをroute.queryから取得して、一覧の内容を更新するパターンをやってみました。

まず、変数をリアクティブにするために、Vueからrefを、setup関数内ではthisを使わないので、Vue RouterからuseRouteをインポートします。

<script>
import { ref } from 'vue'
import { useRoute, onBeforeRouteUpdate } from 'vue-router'

これでthis.$routeと同様のデータをsetup関数内で取得できるようになります。

続いて、ページネーションに必要なデータを初期化します。

<script>
import { ref } from 'vue'
import { useRoute, onBeforeRouteUpdate } from 'vue-router'

export default {
  name: 'Articles',
  setup () {
    const route = useRoute()
    const perpage = 10;
    let page = ref(0);
    let offset = ref(0);
    let list = ref([]);

    page.value = (route.query.page)? parseInt(route.query.page): 1;
  }
}

「list」が一覧ページという想定です。最後のpage.valueの処理は、ページを初期ロードした際の処理です。リアクティブにした変数は「変数名.value」でアクセスする点がポイントです。

次に、route.queryの内容を読み取ってoffsetを格納する関数を用意します。

<script>
import { ref } from 'vue'
import { useRoute, onBeforeRouteUpdate } from 'vue-router'

export default {
  name: 'Articles',
  setup () {
    const route = useRoute()
    const perpage = 10;
    let page = ref(0);
    let offset = ref(0);
    let list = ref([]);

    page.value = (route.query.page)? parseInt(route.query.page): 1;

    const setOffset = ()=> {
      offset.value = (page.value > 0)? parseInt((page.value - 1)) * perpage: 0;
    }
  }
}

こちらは、ページャーでページ遷移する時を想定しています。

次に、一覧の取得を関数化します。こちらはAPIなどからデータを取ってくる想定です。

<script>
import { ref } from 'vue'
import { useRoute, onBeforeRouteUpdate } from 'vue-router'

export default {
  name: 'Articles',
  setup () {
    const route = useRoute()
    const perpage = 10;
    let page = ref(0);
    let offset = ref(0);
    let list = ref([]);

    page.value = (route.query.page)? parseInt(route.query.page): 1;

    const setOffset = ()=> {
      offset.value = (page.value > 0)? parseInt((page.value - 1)) * perpage: 0;
    }
    const load = async () => {
      list.value = await getAPI((offset.value, perpage); // getAPI: APIからデータを取る関数を別途定義したとする
    }
  }
}

ここまでできたら、ページを読み込んだ時の処理を完了させます。

<script>
import { ref } from 'vue'
import { useRoute, onBeforeRouteUpdate } from 'vue-router'

export default {
  name: 'Articles',
  setup () {
    const route = useRoute()
    const perpage = 10;
    let page = ref(0);
    let offset = ref(0);
    let list = ref([]);

    page.value = (route.query.page)? parseInt(route.query.page): 1;

    const setOffset = ()=> {
      offset.value = (page.value > 0)? parseInt((page.value - 1)) * perpage: 0;
    }
    const load = async () => {
      list.value = await getAPI((offset.value, perpage); // getAPI = APIからデータを取る関数を何か定義したとする
    }
    setOffset()
    load()

    return {
      perpage,
      page,
      list
    }
  }
}

最後のreturnで必要な変数をコンポーネントから読み取れるようにするのを忘れないように。

これでページをロードした時の処理はできたので、あとは同じコンポーネントでページ遷移するページネーション処理を定義します。ここは「onBeforeRouteUpdate」を使います。

<script>
import { ref } from 'vue'
import { useRoute, onBeforeRouteUpdate } from 'vue-router'

export default {
  name: 'Articles',
  setup () {
    const route = useRoute()
    const perpage = 10;
    let page = ref(0);
    let offset = ref(0);
    let list = ref([]);

    page.value = (route.query.page)? parseInt(route.query.page): 1;

    const setOffset = ()=> {
      offset.value = (page.value > 0)? parseInt((page.value - 1)) * perpage: 0;
    }
    const load = async () => {
      list.value = await getAPI((offset.value, perpage); // getAPI = APIからデータを取る関数を何か定義したとする
    }
    setOffset()
    load()

    onBeforeRouteUpdate(async (to, from) => {
      if (to.query.page !== from.query.page) {
        page.value = to.query.page;
        setOffset()
        load()
      }
    })

    return {
      perpage,
      page,
      list
    }
  }
}

これで、ページャーがrouter-linkなりで同じコンポーネント内でページ遷移した際に、動的にlistの内容を変更できるようになります。

書き方的にはあまり綺麗ではないですが、これまでdataやcomputed、methodsなどでバラバラに書いていた処理がsetup関数内で一括できるのは良いですね。

: vue3

Author

Koji Kadoma
Member of codit.work

新着ノート

新着コード