在 Laravel 中使用 Vue 實現滾動載入

在工作中有做到通知功能,想說可以讓通知呈現像 FB 這樣的效果

安裝 vue-infinite-loading

vue-infinite-loading

npm

npm install vue-infinite-loading -S

CDN

<script src="https://unpkg.com/vue-infinite-loading@^2/dist/vue-infinite-loading.js"></script>

Component

在組件中使用

<template>
<infinite-loading></infinite-loading>
</template>

<script>
import InfiniteLoading from 'vue-infinite-loading';

export default {
components: {
InfiniteLoading,
},
};
</script>

範例

Vue

InfiniteLoading組件放在列表的底部,監聽infinite事件觸發infiniteHandler方法,當滾動資料載入完畢,則顯示無通知,可以利用slot 特殊屬性來配置不同情況。

並通過$state.loaded方法告訴這個插件我們還有數據,如果 API 返回一個空數組,我們將通過$state.complete方法告訴這個插件所有數據都已加載。

<template>
<div v-for="(item, index) in notifications" :key="item.id">
<!-- 通知迴圈 -->
</div>

<infinite-loading @infinite="infiniteHandler">
<div slot="spinner">載入中...</div>
<div slot="no-more">無更多通知</div>
<div slot="no-results">
暫無通知
</div></infinite-loading
>
</template>

<script>
import InfiniteLoading from 'vue-infinite-loading';

export default {
components: {
InfiniteLoading,
},
data: () => ({
notifications: [],
page: 0
}),
methods: {
/**
* 滾動載入通知.
*/
infiniteHandler($state) {
axios
.get("/notifications", {
params: { page: (this.page = this.page += 1) },
})
.then(({ data: { total, notifications } }) => {
this.total = total;
notifications.data.map(({ id, data, created }) => {
this.notifications.push({
id: id,
title: data.title,
body: data.body,
created: created,
action_url: data.action_url,
img_url: data.img_url,
});
});
if (notifications.current_page == notifications.last_page) {
$state.complete();
} else {
$state.loaded();
}
});
},
}
};
</script>

Controller

controller取得資料庫未讀通知的分頁資料,可改變page參數取得不同頁數資料,通過此網址範例https://example.com.tw/notifications?page=1訪問,

public function __construct()
{
$this->middleware('auth');
}
public function index(Request $request)
{
$user = $request->user(); // 當前user
$query = $user->unreadNotifications(); // 取得未讀訊息
$notifications = $query->paginate(5); // 通知五個為一頁
$notifications->getCollection()->transform(function ($value) {
// 日期時間轉換為 ISO 8601
$value->created = $value->created_at->toIso8601String();
return $value;
});
$total = $user->unreadNotifications->count(); // 未讀訊息數

return compact('notifications', 'total');
}