Posted at

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


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


環境


  • 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