---
# System prepended metadata

title: 在Laravel中使用Vue實現滾動載入
tags: [PHP, ' Vue', ' Backend', ' Laravel']

---

---
tags: PHP, Laravel, Backend, Vue
---

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

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

## 安裝vue-infinite-loading

[vue-infinite-loading](https://github.com/PeachScript/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

在組件中使用

```javascript=
<template>
  <infinite-loading></infinite-loading>
</template>

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

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

## 範例

### Vue

將`InfiniteLoading`組件放在列表的底部，監聽`infinite`事件觸發`infiniteHandler`方法，當滾動資料載入完畢，則顯示無通知，可以利用[slot特殊屬性](https://vuejs.org/v2/api/index.html#slot)來配置不同情況。

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

```javascript=
<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`訪問，

```php=
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');
}
```

更詳細介紹請看[Documentation](https://peachscript.github.io/vue-infinite-loading/)