คอมโพเนนต์ Vue Suspense
พร้อมสล็อต default และ #fallback การโหลดคอมโพเนนต์แบบอะซิงโครนัส และ Suspense ซ้อนกัน
คอมโพเนนต์ Vue Suspense เป็นบทเรียน Vue Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Vue Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Vue Academy มีบทเรียนทั้งหมด 4 บทเรียน
ปัญหาที่ Suspense แก้ได้
Suspense คือคอมโพเนนต์ Vue ในตัวที่ประสานสถานะการโหลดสำหรับคอมโพเนนต์ที่มีการพึ่งพาแบบอะซิงโครนัส
หากไม่มีสิ่งนี้ คอมโพเนนต์แบบอะซิงโครนัสแต่ละรายการจะต้องจัดการตัวหมุนแสดงการโหลดของตนเอง แต่เมื่อใช้ Suspense คุณจะประกาศขอบเขตเดียวที่รอการทำงานแบบอะซิงโครนัสที่ซ้อนกันทั้งหมด และแสดงเนื้อหาสำรองเดียวจนกว่าทุกอย่างจะพร้อม
สองช่อง: เนื้อหาหลักและเนื้อหาสำรอง
Suspense เปิดเผยช่องที่มีชื่อไว้สองช่อง:
- default — เนื้อหาจริง ซึ่งอาจมีคอมโพเนนต์แบบอะซิงโครนัสหรือ
setup()แบบอะซิงโครนัส - fallback — สิ่งที่จะแสดงขณะที่ช่อง default กำลังแก้ไขการพึ่งพา
เมื่อการพึ่งพาแบบอะซิงโครนัสทั้งหมดเสร็จสิ้น Vue จะแทนที่เนื้อหาสำรองด้วยเนื้อหาหลัก
<template>
<Suspense>
<template #default>
<UserDashboard />
</template>
<template #fallback>
<div class="spinner">Loading dashboard...</div>
</template>
</Suspense>
</template>setup() แบบอะซิงโครนัสในฐานะการพึ่งพา
คอมโพเนนต์จะกลายเป็นการพึ่งพาแบบอะซิงโครนัสเมื่อฟังก์ชัน setup() ของคอมโพเนนต์ประกาศเป็น async และรอการทำงานบางอย่าง Vue จะติดตามพรอมิสที่ส่งคืนมา
รูปแบบที่เทียบเท่ากันของ <script setup> คือการใช้ await ระดับบนสุดโดยตรงภายในบล็อก
<script setup>
import { ref } from 'vue'
// Top-level await makes this an async dependency of Suspense
const res = await fetch('/api/profile')
const profile = ref(await res.json())
</script>
<template>
<h1>Welcome, {{ profile.name }}</h1>
</template>คอมโพเนนต์แบบอะซิงโครนัสก็นับรวมด้วย
คอมโพเนนต์ที่สร้างด้วย defineAsyncComponent จะถูกติดตามโดย Suspense เช่นกัน เนื้อหาสำรองจะยังคงแสดงจนกว่า import() แบบไดนามิกจะแก้ไขเสร็จ
วิธีนี้ช่วยให้คุณแบ่งโค้ดของคอมโพเนนต์ขนาดใหญ่โดยไม่ต้องเขียนส่วนติดต่อผู้ใช้สำหรับการโหลดแยกในแต่ละคอมโพเนนต์
<script setup>
import { defineAsyncComponent } from 'vue'
const Chart = defineAsyncComponent(() =>
import('./HeavyChart.vue')
)
</script>
<template>
<Suspense>
<Chart />
<template #fallback>Preparing chart...</template>
</Suspense>
</template>การรอคอมโพเนนต์ลูกแบบอะซิงโครนัสหลายรายการร่วมกัน
หากช่องเริ่มต้นมีการพึ่งพาแบบอะซิงโครนัสหลายรายการ Suspense จะรอให้ทั้งหมดดำเนินการเสร็จสมบูรณ์ก่อนแสดงเนื้อหา
วิธีนี้ช่วยป้องกันการเลื่อนของเค้าโครงจากคอมโพเนนต์ที่ปรากฏทีละรายการ
<template>
<Suspense>
<div>
<UserStats /> <!-- async setup -->
<RecentOrders /> <!-- async setup -->
<Recommendations /> <!-- async component -->
</div>
<template #fallback>
<PageSkeleton />
</template>
</Suspense>
</template>การดักจับการปฏิเสธด้วย onErrorCaptured
หาก setup() แบบอะซิงโครนัสไม่สำเร็จ (เช่น การดึงข้อมูลล้มเหลว) ข้อผิดพลาดจะส่งต่อขึ้นไปยังฮุก onErrorCaptured ที่อยู่ใกล้ที่สุดในคอมโพเนนต์แม่
Suspense เองไม่แสดงข้อผิดพลาด ดังนั้นจึงควรใช้ร่วมกับขอบเขตข้อผิดพลาด
<script setup>
import { ref, onErrorCaptured } from 'vue'
const error = ref(null)
onErrorCaptured((err) => {
error.value = err
return false // stop the error from propagating further
})
</script>รูปแบบขอบเขตข้อผิดพลาดร่วมกับ Suspense
รูปแบบที่ใช้กันทั่วไปในระบบจริงคือการครอบ Suspense ไว้ภายในคอมโพเนนต์ขอบเขตข้อผิดพลาด โดย onErrorCaptured จะคืนค่า false เพื่อหยุดการส่งต่อและแสดงส่วนติดต่อผู้ใช้สำหรับข้อผิดพลาดแทน
<script setup>
import { ref, onErrorCaptured } from 'vue'
const err = ref(null)
onErrorCaptured((e) => { err.value = e; return false })
</script>
<template>
<p v-if="err">Failed to load: {{ err.message }}</p>
<Suspense v-else>
<ProfilePanel />
<template #fallback>Loading...</template>
</Suspense>
</template>เหตุการณ์ @pending และ @resolve
Suspense ส่งเหตุการณ์วงจรชีวิตที่คุณสามารถรับฟังได้ดังนี้:
- @pending — ถูกเรียกเมื่อเข้าสู่สถานะรอดำเนินการ (กำลัง loading)
- @resolve — ถูกเรียกเมื่อช่องเริ่มต้นดำเนินการเสร็จสมบูรณ์
- @fallback — ถูกเรียกเมื่อแสดงเนื้อหา fallback
มีประโยชน์สำหรับการวิเคราะห์การใช้งานหรือแถบความคืบหน้า
<template>
<Suspense @pending="onPending" @resolve="onResolve">
<RouteView />
<template #fallback>Loading route...</template>
</Suspense>
</template>พร็อพ timeout สำหรับ fallback ที่ล่าช้า
พร็อพ timeout (หน่วยเป็นมิลลิวินาที) จะหน่วงการแสดง fallback หากงานแบบอะซิงโครนัสเสร็จเร็วกว่าค่า timeout ก็จะไม่แสดง fallback
วิธีนี้ช่วยป้องกันไม่ให้ตัวหมุนโหลดปรากฏขึ้นชั่วขณะสำหรับการตอบกลับที่รวดเร็ว
<template>
<!-- Only show fallback if loading exceeds 200ms -->
<Suspense :timeout="200">
<FastPanel />
<template #fallback>Loading...</template>
</Suspense>
</template>Suspense กับเราเตอร์และการเปลี่ยนผ่าน
Suspense สามารถใช้ร่วมกับ RouterView และ Transition เพื่อทำให้การเปลี่ยนเส้นทางแบบอะซิงโครนัสมีภาพเคลื่อนไหว ลำดับมีความสำคัญดังนี้: Transition ครอบ Suspense ซึ่งครอบคอมโพเนนต์ของเส้นทางอีกชั้นหนึ่ง
<template>
<RouterView v-slot="{ Component }">
<Transition mode="out-in">
<Suspense>
<component :is="Component" />
<template #fallback>Loading page...</template>
</Suspense>
</Transition>
</RouterView>
</template>เมื่อใด NOT ควรใช้ Suspense
หลีกเลี่ยงการใช้ Suspense กับข้อมูลที่ต้องดึงใหม่บ่อยครั้งขณะที่คอมโพเนนต์ยังติดตั้งอยู่ เพราะ Suspense จะจัดการเฉพาะการดำเนินการแบบอะซิงโครนัสครั้งแรกเท่านั้น สำหรับสถานะกำลังโหลดที่เกิดขึ้นต่อเนื่อง (เช่น การแบ่งหน้าหรือการดึงข้อมูลใหม่) ให้ใช้รีฟแบบรีแอกทีฟ loading ตามปกติแทน
<script setup>
import { ref } from 'vue'
const loading = ref(false)
async function loadMore() {
loading.value = true
await fetchNextPage()
loading.value = false
}
</script>ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับ Suspense
สรุปทบทวน
คุณได้เรียนรู้วิธีที่ Suspense จัดการการพึ่งพาแบบอะซิงโครนัส:
- ช่อง ค่าเริ่มต้นเก็บเนื้อหาแบบอะซิงโครนัส (การตั้งค่าแบบอะซิงโครนัสหรือคอมโพเนนต์แบบอะซิงโครนัส)
- ช่อง fallback จะแสดงระหว่างกำลัง loading
- จะรอคอมโพเนนต์ลูกแบบอะซิงโครนัสทั้งหมดก่อนแสดงเนื้อหา
- การปฏิเสธจะส่งต่อไปยัง
onErrorCapturedในขอบเขตของคอมโพเนนต์แม่ timeoutช่วยป้องกันตัวหมุนโหลดปรากฏขึ้นชั่วขณะ ส่วนเหตุการณ์อย่าง@resolveช่วยในการวิเคราะห์การใช้งาน
เรียนรู้ HTML ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 42
- บทเรียน
- 156
คำถามที่พบบ่อย
บทเรียน “คอมโพเนนต์ Vue Suspense” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “คอมโพเนนต์ Vue Suspense” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Vue Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Vue Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “คอมโพเนนต์ Vue Suspense”
พร้อมสล็อต default และ #fallback การโหลดคอมโพเนนต์แบบอะซิงโครนัส และ Suspense ซ้อนกัน คุณปฏิบัติ Vue Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Vue Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Vue Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “คอมโพเนนต์ Vue Suspense” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Vue Academy นี้ได้ไหม
ได้ บทเรียน Vue Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- คอมโพเนนต์ Vue Suspense
- คอมโพเนนต์แบบอะซิงโครนัสด้วย defineAsyncComponent
- SSR แบบสตรีมด้วย renderToWebStream
- กลยุทธ์การไฮเดรตแบบเลื่อนเวลา