【ライブラリ無し】Laravel + vue で無限スクロール(infinite scroll)を1から実装 - inokawablog

【ライブラリ無し】Laravel + vue で無限スクロール(infinite scroll)を1から実装

pinterst,twitter,facebookなど、最近ではほぼ必ずと言っていいほど使われている無限スクロールをライブラリを使わずスクラッチでLravel と vue.js で実装する。

 

Laravel Framework 5.8.35

vue.js 2.5.17

axios 0.19.0

 

フロント

<template>
  <div class="content">
    <div class="items">
      <div v-for="(item, itemIndex) in items">
        <p>{{item.name}}</p>
      </div>
    </div>
    <!-- ローディングアニメーション -->
    <div class="loading-animation" v-if="itemLoading">
      <img src="https://www.wp-master.club/wp-content/uploads/2018/10/loading.gif" alt="">
    </div>
  </div>
</template>

<script>
  export default {
    data: () => ({
      itemLoading: false,
      load: true,
      page: 1,
      items: [],
    }),

    mounted(){
      this.clearVar()
      window.onscroll = () => {
        let bottomOfWindow = document.documentElement.scrollTop + window.innerHeight == document.documentElement.offsetHeight;
        if (bottomOfWindow) this.getItems();
      };
      this.getItems()
    },

    methods: {
      clearVar() {
        this.itemLoading = false
        this.load = true
        this.page = 1
        this.items = []
      },
      async getItems() {
        if (this.load) { //全体の読み込み
          if (!this.itemLoading) { //読み込み中は読み込めないようにする
            this.itemLoading = true
            try {
              const response = await axios.get('/api/items?page=' + this.page)
              if (response.data.items.last_page == this.page) this.load = false
              if (response.data.items.data) {
                await response.data.items.data.forEach((n,i) => {
                  this.items.push(n)
                })
              }
              this.page += 1
            } catch (e) {
              console.log(e.response)
              this.load = false
              this.itemLoading = false
            } finally {
              this.itemLoading = false
            }
          }
        }
      },
    }
  }
</script>

 

mountedのタイミングで画面高さを取得して、bottomに言ったらgetItemsが発火します。getItemsはapiでcontrollerからデータを持ってきているだけです。

 

難しいことはしてません。上からゆっくり読んでいけばわかります。

 

バックエンド

controller

paginateで持ってくる

public function getItems()
  {
    $items = Item::latest()->paginate(10);
    return ['items' => $items];
  }

 

 

まとめ

融通が効かない場合もあったりするので、なんでもライブラリを使わず、できるものはなるべく自作していきたい。