Vue 3 Teleport ve Suspense: İleri Düzey Kalıplar ve Mülakat Soruları 2026

Vue 3 Teleport ve Suspense için kapsamlı rehber - ileri düzey render kalıpları, hata yönetimi ve kıdemli Vue geliştiricileri için sık sorulan mülakat soruları.

Vue 3 Teleport ve Suspense ileri düzey kalıplar

Vue 3 Teleport ve Suspense iki farklı render sorununu çözer: bileşenleri DOM hiyerarşileri dışına yerleştirmek ve asenkron bağımlılıkları koordine etmek. Her ikisi de import gerektirmeyen yerleşik bileşenlerdir ve her ikisi de kıdemli Vue geliştirici mülakatlarında sıkça karşımıza çıkar.

Vue 3.5 Teleport Güncellemesi

Vue 3.5, Teleport'a defer prop'unu ekledi ve bileşen ağacında daha sonra render edilen hedeflere izin veriyor. Bu, portal hedefinin mount zamanında var olmadığı yaygın SSR zamanlama sorununu çözer.

Teleport Temelleri ve defer Prop

Teleport, render edilen içeriği farklı bir DOM konumuna taşırken Vue bileşen ağacını korur. Bileşen, ebeveyninin mantıksal çocuğu olarak kalır: props, olaylar ve provide/inject normal şekilde çalışır. Vue DevTools, teleport edilen bileşeni hedef elementin altında değil, ebeveyninin altında iç içe geçmiş olarak gösterir.

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>

to prop'u bir CSS seçici string veya DOM element referansı kabul eder. Hedef mount zamanında var olmadığında, Teleport uyarı verir ve hiçbir şey render etmez. Bu, SSR ve dinamik layout'larla sorunlar yaratır.

defer Prop (Vue 3.5+)

defer prop'u, Teleport'a hedefi çözmeden önce uygulamanın diğer bölümlerinin mount olmasını beklemesini söyler. Bu, aynı bileşende veya kardeş bileşenlerde daha sonra render edilen elementlere teleport etmeyi mümkün kılar.

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

  <!-- Target rendered after the Teleport -->
  <div id="dynamic-target"></div>
</template>

defer olmadan bu kod başarısız olur çünkü Teleport mount olduğunda #dynamic-target var değildir. defer ile Vue, aynı tick'teki tüm bileşenler mount olduktan sonra hedefi çözer. Hedef yine de aynı mount veya güncelleme döngüsünde render edilmelidir.

Çoklu Teleport'lar ve Koşullu Render

Birden fazla Teleport bileşeni aynı elementi hedefleyebilir. İçerik, deklarasyon sırasına göre eklenir:

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

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

<!-- Result in #notifications:
  <div>First</div>
  <div>Second</div>
-->

disabled prop'u teleportasyonun gerçekleşip gerçekleşmeyeceğini kontrol eder. Devre dışı bırakıldığında içerik inline render edilir. Bu kalıp, modallerin masaüstünde üstte görünmesi ama mobilde inline render edilmesi gereken responsive layout'ları yönetir:

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

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

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

Asenkron Bileşen Orkestrasyonu için Suspense

Suspense, bileşen ağacı boyunca asenkron bağımlılıkları koordine eder. Herhangi bir alt bileşen çözülmemiş asenkron bağımlılığa sahip olduğunda, Suspense fallback slot içeriğini görüntüler. Tüm bağımlılıklar çözüldüğünde, Suspense varsayılan slot'a geçer.

Deneysel Durum

Suspense, Vue 3.5'te deneysel olarak kalmaya devam ediyor. API, kararlı duruma ulaşmadan önce değişebilir. Üretim kullanımı bu riski kabul etmeyi gerektirir.

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

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

Suspense iki tür asenkron bağımlılığı izler: async setup() içeren bileşenler ve defineAsyncComponent ile oluşturulan asenkron bileşenler.

Top-Level Await ile Async Setup

Vue 3 script setup, top-level await'i destekler. Top-level await kullanan herhangi bir bileşen, Suspense'in izleyebileceği bir asenkron bağımlılık haline gelir:

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>

Bu bileşen, fetch tamamlanana kadar render edilemez. Üst Suspense sınırı, çözüme kadar fallback'i görüntüler. Suspense sınırı olmadan bileşen basitçe render edilmez.

suspensible Prop ile İç İçe Suspense

Karmaşık uygulamalar genellikle birden fazla asenkron sınıra sahiptir. Vue 3.3, iç içe geçmiş Suspense bileşenlerinin ebeveynleriyle nasıl etkileşime girdiğini kontrol etmek için suspensible prop'unu tanıttı.

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

      <main>
        <!-- Inner Suspense with its own fallback -->
        <Suspense suspensible>
          <template #default>
            <AsyncContent />
          </template>
          <template #fallback>
            <ContentSkeleton />
          </template>
        </Suspense>
      </main>
    </template>

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

suspensible ayarlandığında, iç Suspense üst Suspense sınırına kaydolur. Ebeveyn, fallback'ini gizlemeden önce hem AsyncNavigation hem de AsyncContent'in çözülmesini bekler. İç Suspense hâlâ yerel sınır olarak görev yapar: AsyncContent daha uzun sürerse, AsyncNavigation görünür kalırken ContentSkeleton görüntülenir.

suspensible olmadan, iç Suspense bağımsız olarak çalışır. Ebeveyn, fallback'ini yalnızca AsyncNavigation yüklenirken gösterir ve AsyncContent'i tamamen görmezden gelir.

Vue.js / Nuxt.js mülakatlarında başarılı olmaya hazır mısın?

İnteraktif simülatörler, flashcards ve teknik testlerle pratik yap.

Teleport, Suspense ve Transition'ların Birleştirilmesi

Gerçek uygulamalar bu kalıpları birleştirir. İçeriği asenkron olarak yükleyen bir modal, üçünden de faydalanır:

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>

İç içe geçme sırası önemlidir: Teleport, Transition'ı sarar; Transition, koşullu elementi sarar; koşullu element Suspense'i içerir. Bu, geçişin yükleme durumları dahil tüm modal'ı animasyonlu hale getirmesini sağlar.

Suspense ile Hata Yönetimi

Suspense hataları yönetmez. Başarısız asenkron bağımlılıklar promise'lerini reddeder ve hataları bileşen ağacında yukarı yayar. onErrorCaptured yaşam döngüsü hook'u bu hataları sınırda yakalar:

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

const error = ref(null)

onErrorCaptured((err) => {
  error.value = err
  return false // Prevent propagation
})
</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>

Bu kalıp, herhangi bir asenkron bileşen ağacını hem yükleme hem de hata durumlarıyla sarar. Yeniden deneme düğmesi hatayı temizler ve Vue'nun yeniden render edip asenkron işlemi tekrar denemesine neden olur.

Teleport ve Suspense Mülakat Soruları

Kıdemli Vue pozisyonları bu kalıpları giderek daha fazla test ediyor. Yaygın sorular ve güçlü cevapları ayıran özellikler:

S: Teleport ne zaman CSS konumlandırması yerine kullanılmalıdır?

Zayıf cevap: "z-index çalışmadığında."

Güçlü cevap: Teleport, CSS'in çözemediği DOM hiyerarşi sorunlarını çözer. overflow: hidden veya transform içeren bir konteynerin içindeki modal yeni bir stacking context oluşturur ve position: fixed'i bozar. Teleport, modal'ı body'ye taşır, Vue'nun mantıksal bileşen ağacını korurken bu kısıtlamalardan kaçar.

S: Suspense, her bileşendeki yükleme durumlarından nasıl farklıdır?

Zayıf cevap: "Suspense daha temiz."

Güçlü cevap: Suspense birden fazla asenkron bağımlılığı koordine eder. Bireysel yükleme durumlarına sahip on bileşen, farklı zamanlarda on spinner yanıp söner. Suspense, onu çözene kadar tek spinner gösterir, sonra hepsini birlikte ortaya çıkarır. Bu, daha pürüzsüz algılanan performans ve daha basit bileşen kodu oluşturur çünkü asenkron bileşenler kendi yükleme durumlarını yönetmek zorunda kalmaz.

S: Teleport hedefi var olmadığında ne olur?

İçerik render edilmez ve Vue uyarı kaydeder. Vue 3.5'teki defer prop'u, diğer bileşenlerin önce mount olmasını bekleyerek bunu çözer. defer olmadan, hedeflerin index.html'de veya çocuklardan önce mount olan bir üst bileşende var olduğundan emin olunmalıdır.

S: Suspense, Options API ile çalışır mı?

Evet. async setup() içeren herhangi bir bileşen, başka yerlerde Composition API veya Options API kullanıp kullanmadığına bakılmaksızın Suspense'i tetikler. Asenkron sınır, bileşen stili değil setup fonksiyonudur.

Nuxt 3'te Teleport ve Suspense

Nuxt 3, bu kalıpları SSR değerlendirmeleriyle genişletir. SSR hakkında Nuxt belgeleri hidrasyon zamanlamasını kapsar.

Teleport için Nuxt, hedefin hidrasyondan önce var olmasını gerektirir. Portal hedeflerini app.vue'ya ekleyin veya defer prop'unu kullanın:

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

  <!-- Portal targets for SSR -->
  <div id="modal-root"></div>
  <div id="toast-root"></div>
</template>

Suspense için Nuxt'un useFetch ve useAsyncData composable'ları otomatik olarak entegre olur. Bu composable'ları kullanan sayfa bileşenleri, manuel yapılandırma olmadan Nuxt'un yerleşik Suspense'iyle çalışır. İlgili mülakat hazırlığı için SharpSkill Vue composables modülüne bakın.

Vue 3.5 için Üretim Kalıpları

  • index.html'de Teleport hedefleri: Herhangi bir Vue kodu çalışmadan önce var olan kararlı portal hedefleri oluşturun. Bu, zamanlama sorunlarını tamamen önler.
  • Granüler Suspense sınırları: Bağımsız yükleme birimi başına bir Suspense. Ayrı widget'lara sahip bir dashboard, ayrı Suspense sınırlarından faydalanır, böylece hızlı widget'lar hemen görünür.
  • Suspense'in üstünde hata sınırları: Suspense'i her zaman hata yönetimiyle sarın. Ağ hataları ve API hataları tüm ağacı çökertmemelidir.
  • Geçiş zamanlaması: Suspense'i Transition ile birleştirirken, durum değişiklikleri sırasında örtüşmeyi önlemek için mode="out-in" ayarlayın.

Pratik yapmaya başla!

Mülakat simülatörleri ve teknik testlerle bilgini test et.

Günün meydan okuması

Vue.js / Nuxt.js kodundaki hatayı bulabilir misin?

Gerçek bir kod parçası, gizli bir hata, günde bir deneme. Denemek için hesap gerekmez.

Anthony Fillion-Maillet

Yazan:

Anthony Fillion-Maillet

SharpSkill kurucusu

10 yılı aşkın süredir fullstack geliştirici. SharpSkill’i yönetiyor ve burada yayımlanan her şeyden sorumlu.

28 Ağustos 2026 tarihinde güncellendi

Etiketler

#vue 3
#teleport
#suspense
#vue ileri düzey
#mülakat soruları

Paylaş

İlgili makaleler