LoginSignup
4

More than 3 years have passed since last update.

LaravelとVue(axios)でVue-infinite-loadingで無限ローディングを実装する

Posted at

ツイッターとか使ってるとタイムラインを無限に更新するアレを実装してみる。

環境

  • Laravel 5.7
  • Vue.js 2.5.17
  • axios 0.19

 事前準備

  • 上記の環境構築済み

Vue-infinite-loadingをインストール

これだけでインストールできます

npm install vue-infinite-loading

Laravel側の設定

Migration

database/migrations/2019_07_15_123456_create_posts_table.php

リレーションなしでシンプルな記事一覧用のテーブル

2019_07_15_123456_create_posts_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title')->comment('記事タイトル');
            $table->string('text')->comment('記事本文');
            $table->timestamps();

            $table->index('id');
            $table->index('title');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

Model

app/Post.php

Post.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //記事データの取得
    static function getPostPage()
    {
        //10件データを取得する
        $data = Post::paginate(10);

        return $data;
    }

}

Controller

app/Http/Controllers/PostsController.php

メソッドを呼び出す

PostsController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Post;

class PostsController extends Controller
{
    public function blog()
    {
        $blogs = Post::getPostPage();

        return $blogs;
    }
}

Routing

routes/web.php

URLで/api/postを叩くとデータを取得できる

web.php
// Post
Route::get('api/post', 'PostsController@blog');

Vue側の設定

Vue-infinite-loadingを使用する

resources/js/app.js

app.js
import './bootstrap';
import Vue from 'vue';
import Routes from './routes.js';
import InfiniteLoading from 'vue-infinite-loading';

//Vue-infinite-loadingを使用する
Vue.use(InfiniteLoading);

const app = new Vue({
    el: '#app',
    router: Routes,
    render: h => h(App)
});

export default app;

コンポーネントを設定する

resources/js/components/Blog.vue

routes.js
import Vue from 'vue';
import VueRouter from 'vue-router';

//ページコンポーネントをインポートする
import Blog from './components/Blog';

//VueRouterプラグインを使用する
Vue.use(VueRouter);

//パスとコンポーネントのマッピングを行う
const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/blog',
            name: 'Blog',
            component: Blog
        }
    ]
});

//app.jsでインポートするためにVueRouterインスタンスをエクスポートする
export default router;

View

resource/js/conponents/Blog.vue

Blog.vue
<template>
    <div class="col-md-12">
        <div v-for="post in posts" :key="post.index">                                               
            <h1>{{ post.title }}</h1>
            <p :key="post.index">{{ post.text }}</p>
        </div>
        <infinite-loading @infinite="infiniteHandler"></infinite-loading>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                page: 1,
                posts: []
            };
        },
        methods: {
            infiniteHandler($state) {
                //web.phpで設定したルーティング
                axios.get('/api/post', {
                    params: {
                        page: this.page,
                        per_page: 1
                    },
                }).then(({ data }) => {
                    //そのままだと読み込み時にカクつくので1500毎に読み込む
                    setTimeout(() => {
                        if (this.page < data.data.length) {
                            this.page += 1
                            this.posts.push(...data.data)
                            $state.loaded()
                        } else {
                            $state.complete()
                        }
                    }, 1500)
                }).catch((err) => {
                    $state.complete()
                })
            }
        }
    };
</script>

これで動くはず。。( ◠‿◠ )

参考

Vue-infinite-loading公式
Laravel Vue JS Infinite Scroll Example with Demo

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4