---
url: /blog-vue/use-suspense-to-load-components-asynchronously.md
description: 切換頁面卡卡有很多種原因，這裡舉的例子只針對元件太大的情境。除了想辦法拆分外，還有一個方法就是利用 Vue 的 Async Component。
---

![use-suspense-to-load-components-asynchronously](/use-suspense-to-load-components-asynchronously.webp){.cover}

# Vue 元件太肥，切換頁面卡卡怎麼辦？讓 Suspense 登場吧！

醜話說在前頭，切換頁面卡卡有很多種原因，這裡舉的例子只針對元件太大的情境喔。( •̀ ω •́ )✧

甚麼樣的情況會讓元件太大呢？有可能是 HTML、CSS 太多，但最常見的情況就是包了太多 JS 在一起了。╮(╯▽╰)╭（import 一大堆套件等等）

除了想辦法拆分外，還有一個方法就是利用 Vue 的 Async Component。

## Async Component 是什麼？

甚麼是 [Async Component](https://vuejs.org/guide/components/async)？簡單來說就是在真的要用的時候才從 server 下載元件，如果熟悉 Vue Router 的朋友們對以下寫法一定不陌生：

```ts
const router = createRouter({
  // ...
  routes: [
    {
      path: '/users/:id',
      component: () => import('./views/UserDetails.vue')
    },
  ],
})
```

這個在 Vue Router 中被稱為 [Lazy Loading Routes](https://router.vuejs.org/guide/advanced/lazy-loading.html)。

此概念與 Async Component 概念相同，編譯、打包時會將每個頁面拆分，只有在真的需要某頁面元件時，才從 server 下載，才不會讓進入網頁的使用者等待下載一堆還不會用到的頁面。

讓我們來一個簡單的範例：

`App.vue`

```vue
<script setup>
import FatComp from './components/FatComp.vue'
</script>

<template>
  Vue Suspense

  <hr>

  <fat-comp />
</template>
```

其中 FatComp 是一個和鱈魚一樣超肥的元件，會顯示「很大很大的元件」。

鱈魚：「說好的尊重呢？(ﾟДﾟ\*)ﾉ」

如果我們直接 import 元件，就必須等待元件下載完成，`App.vue` 的畫面才會出現。

![同步載入](/use-suspense-to-load-components-asynchronously/sync.gif){width="240px" format="gif"}

可以注意到 Vue Suspense 的文字會等到 FatComp 載入完成後才會顯示。

如果我們使用 Suspense 改寫：

```vue
<script setup>
import { defineAsyncComponent } from 'vue'

const AsyncFatComp = defineAsyncComponent(() =>
  import('./components/FatComp.vue')
)
</script>

<template>
  Vue Suspense

  <hr>

  <Suspense>
    <async-fat-comp />

    <template #fallback>
      Loading...
    </template>
  </Suspense>
</template>
```

![非同步載入](/use-suspense-to-load-components-asynchronously/async.gif){width="240px" format="gif"}

可以看到 Vue Suspense 字樣先出現，肥肥的元件則會等到下載完成才出現。

恭喜頁面不卡了！✧⁑｡٩(ˊᗜˋ\*)و✧⁕｡

Suspense 元件詳細說明可以來[官方文件](https://cn.vuejs.org/guide/built-ins/suspense)看看。

以上[範例程式在此](https://stackblitz.com/edit/vue-suspense-cmte55?file=src%2FApp.vue\&terminal=dev)，我們下次再見囉！(´▽\`ʃ♡ƪ)

## 總結 🐟

* 肥大元件請用 Async Component
* 配合 Suspense 可以讓頁面有更好的使用者體驗
