ツイッターとか使ってるとタイムラインを無限に更新するアレを実装してみる。
環境
- 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