Vue 3 Teleport va Suspense: Cac Mau Nang Cao va Cau Hoi Phong Van 2026

Tim hieu cac mau nang cao Vue 3 Teleport va Suspense cho phong van developer senior. Huong dan day du voi code vi du va best practices 2026.

Vue 3 Teleport va Suspense: Cac Mau Nang Cao va Cau Hoi Phong Van 2026

Vue 3 Teleport va Suspense giai quyet hai thach thuc rendering khac nhau: dat component ngoai hierarchy DOM va dieu phoi cac dependency async. Ca hai deu la component tich hop san khong can import, va ca hai deu thuong xuat hien trong phong van developer Vue senior.

Cap Nhat Vue 3.5 Teleport

Vue 3.5 da them prop defer vao Teleport, cho phep target duoc render sau trong component tree. Dieu nay giai quyet van de timing SSR pho bien khi target portal khong ton tai tai thoi diem mount.

Can Ban Teleport va Prop defer

Teleport di chuyen noi dung da render den vi tri DOM khac trong khi van duy tri component tree cua Vue. Component van la child logic cua parent: props, events, va provide/inject deu hoat dong binh thuong. Vue DevTools hien thi component duoc teleport nam duoi parent cua no, khong phai duoi element target.

vue
<!-- ModalTrigger.vue -->
<script setup>
import { ref } from 'vue'

const isOpen = ref(false)
</script>

<template>
  <button @click="isOpen = true">Open Modal</button>

  <Teleport to="#modal-root">
    <div v-if="isOpen" class="modal-overlay" @click.self="isOpen = false">
      <div class="modal-content">
        <slot />
        <button @click="isOpen = false">Close</button>
      </div>
    </div>
  </Teleport>
</template>

Prop to nhan chuoi CSS selector hoac tham chieu element DOM. Khi target khong ton tai tai thoi diem mount, Teleport phat ra warning va khong render gi. Dieu nay tao ra van de voi SSR va layout dong.

Prop defer (Vue 3.5+)

Prop defer yeu cau Teleport cho doi cho den khi cac phan khac cua ung dung da mount truoc khi giai quyet target. Dieu nay cho phep teleport den cac element duoc render sau trong cung component hoac cac component anh em.

vue
<!-- App.vue -->
<template>
  <Teleport defer to="#dynamic-target">
    <NotificationBanner />
  </Teleport>

  <!-- Target duoc render sau Teleport -->
  <div id="dynamic-target"></div>
</template>

Khong co defer, code nay se that bai vi #dynamic-target khong ton tai khi Teleport mount. Voi defer, Vue giai quyet target sau khi tat ca component trong cung tick da mount. Target van phai duoc render trong cung chu ky mount hoac update.

Nhieu Teleport va Conditional Rendering

Nhieu component Teleport co the nham den cung mot element. Noi dung duoc them theo thu tu khai bao:

vue
<template>
  <Teleport to="#notifications">
    <Toast message="First" />
  </Teleport>

  <Teleport to="#notifications">
    <Toast message="Second" />
  </Teleport>
</template>

<!-- Ket qua trong #notifications:
  <div>First</div>
  <div>Second</div>
-->

Prop disabled kiem soat viec teleport co xay ra hay khong. Khi disabled, noi dung duoc render inline. Pattern nay xu ly layout responsive khi modal can overlay tren desktop nhung render inline tren mobile:

vue
<script setup>
import { useMediaQuery } from '@vueuse/core'

const isMobile = useMediaQuery('(max-width: 768px)')
</script>

<template>
  <Teleport to="body" :disabled="isMobile">
    <MobileDrawer />
  </Teleport>
</template>

Suspense cho Dieu Phoi Component Async

Suspense dieu phoi cac dependency async trong toan bo component tree. Khi bat ky component con nao co dependency async chua duoc resolve, Suspense hien thi noi dung slot fallback. Khi tat ca dependency duoc resolve, Suspense chuyen sang slot default.

Trang Thai Thu Nghiem

Suspense van o trang thai thu nghiem trong Vue 3.5. API co the thay doi truoc khi dat trang thai on dinh. Su dung trong production doi hoi chap nhan rui ro nay.

vue
<!-- Dashboard.vue -->
<template>
  <Suspense>
    <template #default>
      <DashboardContent />
    </template>

    <template #fallback>
      <LoadingSpinner />
    </template>
  </Suspense>
</template>

Suspense theo doi hai loai dependency async: component voi async setup() va async component duoc tao bang defineAsyncComponent.

Async Setup voi Top-Level Await

Vue 3 script setup ho tro top-level await. Bat ky component nao su dung top-level await tro thanh dependency async ma Suspense co the theo doi:

vue
<!-- UserProfile.vue -->
<script setup>
const response = await fetch('/api/user/profile')
const user = await response.json()
</script>

<template>
  <div class="profile">
    <h1>{{ user.name }}</h1>
    <p>{{ user.email }}</p>
  </div>
</template>

Component nay khong the render cho den khi fetch hoan thanh. Suspense boundary parent hien thi fallback cho den khi resolve. Khong co Suspense boundary, component don gian khong render.

Nested Suspense voi Prop suspensible

Cac ung dung phuc tap thuong co nhieu async boundary. Vue 3.3 gioi thieu prop suspensible de kiem soat cach cac component Suspense long nhau tuong tac voi parent.

vue
<!-- PageLayout.vue -->
<template>
  <Suspense>
    <template #default>
      <header>
        <AsyncNavigation />
      </header>

      <main>
        <!-- Inner Suspense voi fallback rieng -->
        <Suspense suspensible>
          <template #default>
            <AsyncContent />
          </template>
          <template #fallback>
            <ContentSkeleton />
          </template>
        </Suspense>
      </main>
    </template>

    <template #fallback>
      <PageSkeleton />
    </template>
  </Suspense>
</template>

Khi suspensible duoc dat, Suspense ben trong dang ky voi Suspense boundary parent. Parent cho doi ca AsyncNavigation va AsyncContent resolve truoc khi an fallback. Suspense ben trong van phuc vu nhu boundary cuc bo: neu AsyncContent mat nhieu thoi gian hon, ContentSkeleton hien thi trong khi AsyncNavigation van hien thi.

Khong co suspensible, Suspense ben trong hoat dong doc lap. Parent chi hien fallback khi AsyncNavigation dang load, bo qua AsyncContent hoan toan.

Sẵn sàng chinh phục phỏng vấn Vue.js / Nuxt.js?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Ket Hop Teleport, Suspense, va Transitions

Cac ung dung thuc te ket hop cac pattern nay. Modal tai noi dung async duoc huong loi tu ca ba:

vue
<!-- AsyncModal.vue -->
<script setup>
import { ref, defineAsyncComponent } from 'vue'

const isOpen = ref(false)

const AsyncModalContent = defineAsyncComponent({
  loader: () => import('./ModalContent.vue'),
  loadingComponent: () => import('./ModalSkeleton.vue'),
  delay: 200,
  timeout: 10000
})
</script>

<template>
  <button @click="isOpen = true">Open</button>

  <Teleport to="body">
    <Transition name="modal">
      <div v-if="isOpen" class="modal-wrapper">
        <Suspense>
          <template #default>
            <AsyncModalContent @close="isOpen = false" />
          </template>
          <template #fallback>
            <ModalSkeleton />
          </template>
        </Suspense>
      </div>
    </Transition>
  </Teleport>
</template>

<style>
.modal-enter-active,
.modal-leave-active {
  transition: opacity 0.3s ease;
}

.modal-enter-from,
.modal-leave-to {
  opacity: 0;
}
</style>

Thu tu nesting quan trong: Teleport boc Transition, boc element co dieu kien, chua Suspense. Dieu nay dam bao transition animate toan bo modal bao gom ca loading state.

Xu Ly Loi voi Suspense

Suspense khong xu ly loi. Cac dependency async that bai se reject promise va lan truyen loi len component tree. Lifecycle hook onErrorCaptured bat cac loi nay tai boundary:

vue
<!-- ErrorBoundary.vue -->
<script setup>
import { ref, onErrorCaptured } from 'vue'

const error = ref(null)

onErrorCaptured((err) => {
  error.value = err
  return false // Ngan chan lan truyen
})
</script>

<template>
  <div v-if="error" class="error-state">
    <p>Failed to load: {{ error.message }}</p>
    <button @click="error = null">Retry</button>
  </div>

  <Suspense v-else>
    <template #default>
      <slot />
    </template>
    <template #fallback>
      <slot name="loading" />
    </template>
  </Suspense>
</template>

Pattern nay boc bat ky component tree async nao voi ca loading va error state. Nut retry xoa loi, khien Vue render lai va thu lai thao tac async.

Cau Hoi Phong Van ve Teleport va Suspense

Cac vi tri Vue senior ngay cang kiem tra cac pattern nay. Sau day la cac cau hoi pho bien va dieu gi phan biet cau tra loi manh:

Q: Khi nao nen su dung Teleport thay vi CSS positioning?

Cau tra loi yeu: "Khi z-index khong hoat dong."

Cau tra loi manh: Teleport giai quyet cac van de hierarchy DOM ma CSS khong the. Modal ben trong container voi overflow: hidden hoac transform tao stacking context moi, pha vo position: fixed. Teleport di chuyen modal den body, thoat khoi cac constraint nay trong khi van duy tri component tree logic cua Vue.

Q: Suspense khac voi loading state trong tung component nhu the nao?

Cau tra loi yeu: "Suspense sach hon."

Cau tra loi manh: Suspense dieu phoi nhieu dependency async. Muoi component voi loading state rieng le hien thi muoi spinner tai cac thoi diem khac nhau. Suspense hien thi mot spinner cho den khi ca muoi resolve, sau do hien thi tat ca cung luc. Dieu nay tao ra hieu suat cam nhan muot hon va code component don gian hon vi cac component async khong can quan ly loading state rieng.

Q: Dieu gi xay ra khi target Teleport khong ton tai?

Noi dung khong render va Vue ghi lai warning. Prop defer cua Vue 3.5 giai quyet dieu nay bang cach cho cac component khac mount truoc. Khong co defer, dam bao target ton tai trong index.html hoac trong component parent mount truoc children.

Q: Suspense co hoat dong voi Options API khong?

Co. Bat ky component nao voi async setup() se kich hoat Suspense, bat ke no su dung Composition API hay Options API o noi khac. Ham setup la async boundary, khong phai style component.

Teleport va Suspense trong Nuxt 3

Nuxt 3 mo rong cac pattern nay voi cac can nhac SSR. Tai lieu Nuxt ve SSR bao gom timing hydration.

Voi Teleport, Nuxt yeu cau target ton tai truoc hydration. Them target portal vao app.vue hoac su dung prop defer:

vue
<!-- app.vue -->
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>

  <!-- Target portal cho SSR -->
  <div id="modal-root"></div>
  <div id="toast-root"></div>
</template>

Voi Suspense, useFetch va useAsyncData cua Nuxt tich hop tu dong. Cac component trang su dung cac composable nay hoat dong voi Suspense tich hop san cua Nuxt ma khong can cau hinh thu cong. Xem module Vue composables cua SharpSkill de chuan bi phong van lien quan.

Cac Pattern Production cho Vue 3.5

  • Target Teleport trong index.html: Tao cac target portal on dinh ton tai truoc khi bat ky code Vue nao chay. Dieu nay tranh hoan toan cac van de timing.
  • Suspense boundary chi tiet: Mot Suspense cho moi don vi loading doc lap. Dashboard voi cac widget rieng biet duoc huong loi tu cac Suspense boundary rieng de widget nhanh xuat hien ngay lap tuc.
  • Error boundary tren Suspense: Luon boc Suspense voi xu ly loi. Network failure va API error khong duoc lam crash toan bo tree.
  • Timing transition: Khi ket hop Suspense voi Transition, dat mode="out-in" de ngan chan overlap trong khi thay doi state.

Bắt đầu luyện tập!

Kiểm tra kiến thức với mô phỏng phỏng vấn và bài kiểm tra kỹ thuật.

Thử thách hôm nay

Bạn có tìm ra lỗi trong Vue.js / Nuxt.js không?

Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Anthony Fillion-Maillet

Viết bởi

Anthony Fillion-Maillet

Người sáng lập SharpSkill

Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.

Cập nhật ngày 28 tháng 8, 2026

Chia sẻ

Bài viết liên quan