見出し画像

Rails×Nuxt.jsで無限スクロールを導入する

デモページ

画像1

このクルクルしたやつを無限スクロールというそうです。

まずは参考記事をズラッと全部読むと導入していけると思います。



https://peachscript.github.io/vue-infinite-loading/guide/

https://rightcode.co.jp/blog/information-technology/vue-js-seo-infinite-scroll


記事を読めば導入は可能ですので、私自身がつまずいた点を記述していきます。

最後まで読み込んだあとデータを取得すると挙動がおかしくなる

無限スクロールを一番下まで行ったあとにページリロードやページ遷移し戻ってくるとエラーは発生しません。

しかし私の場合すべてを読み込んだあとに投稿をすると挙動がおかしく、inifityloadingがリセットされず、投稿がありません状態になってしまっていました。

投稿後は「fetchposts(投稿をすべて取得する)メソッド」を発火させていました。

調べていくとエラーが起きる時起きない時の差異は、

ページコンポーネントが作成されているか、使い回されているかで挙動が違うようです。

使い回されている状態でもう一度inifinity loadingを元の状態にするにはidentifierオプションをつけなければなりませんでした。

identifier は識別子という意味です。

Vueのガイドにはもあるのですが、

画像2

画像3

これを参考に作成したコードがこちらです。

inifinityloading部分だけ抜粋

<template>
    <VueInfiniteLoading
     ref="infiniteLoading"
     spinner="bubbles"
     :identifier="infiniteId"
     @infinite="infiniteHandler"
   >
     <span slot="no-more">-----投稿は以上です-----</span>
     <span slot="no-results">----投稿がありません----</span>
   </VueInfiniteLoading>
</template>
<script>
export default {
    data(){
        return {
            page: 1,
            infiniteId: 0 //inifiteIdという変数を用意しておきidentifierとデータバインディング
        }
    },
    methods: {
      infiniteHandler () {
         this.page += 1
         this.$axios.get('/api/v1/posts', { params: { page: this.page } })
           .then((res) => {
             const posts = res.data.posts
             setTimeout(() => {
               if (posts.length !== 0) {
                 this.posts.push(...posts)
                 this.$refs.infiniteLoading.stateChanger.loaded()
               } else {
                 this.$refs.infiniteLoading.stateChanger.complete()
               }
             }, 1000)
           })
       },
       async fetchPost () {
           //投稿をすべて読み込むメソッド。投稿をrails側に送信した瞬間にメソッドを発火させる。その差異一番上の投稿画面に戻らせたいため、resethandllerとgotoTopにしています
         this.resetHandler()
         this.returnTop()
         const url = '/api/v1/posts'
         await this.$axios.get(url)
           .then((res) => {
             this.posts = res.data.posts
             this.$vuetify.goTo(0)
           })
           .catch((err) => {
             // eslint-disable-next-line no-console
             console.error(err)
           })
       },
       resetHandler () {
         this.page = 1
         this.infiniteId += 1 //resetHandlerメソッドを発火させると読み込みページが1ページ目でかつ新たなものとして読み込むことになる
       }
    }
 }
</script>

コード全容はこちらにのっています

https://github.com/missi0415/foodcom/blob/main/front/pages/posts/index.vue

もし同じ困難にぶち当たってしまった人の助けになるといいなと思います。

それでは失礼します。


いいなと思ったら応援しよう!