{"id":37764,"date":"2026-01-14T19:41:03","date_gmt":"2026-01-14T16:41:03","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=37764"},"modified":"2026-01-14T19:41:03","modified_gmt":"2026-01-14T16:41:03","slug":"vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/","title":{"rendered":"Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma"},"content":{"rendered":"<p><body><\/p>\n<h2>Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma<\/h2>\n<p>Modern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini (UX) \u00f6n planda tutarak h\u0131zl\u0131, ak\u0131c\u0131 ve duyarl\u0131 olmal\u0131d\u0131r. Bu hedeflere ula\u015fmada kritik rol oynayan stratejilerden biri de tembel y\u00fckleme (lazy loading) prensibidir. \u00d6zellikle \u00e7ok ad\u0131ml\u0131 formlar veya karma\u015f\u0131k i\u015f ak\u0131\u015flar\u0131 i\u00e7eren sihirbaz (wizard) yap\u0131lar\u0131nda, tembel y\u00fckleme hem performans\u0131 art\u0131r\u0131r hem de kullan\u0131c\u0131lar\u0131n uygulaman\u0131zla etkile\u015fimini iyile\u015ftirir. Bu makalede, Vue.js \u00e7er\u00e7evesinde tembel y\u00fcklenen bir sihirbaz\u0131n nas\u0131l olu\u015fturulaca\u011f\u0131n\u0131, temel konseptlerden ba\u015flayarak ad\u0131m ad\u0131m teknik uygulamalar\u0131na kadar detayl\u0131 bir \u015fekilde inceleyece\u011fiz.<\/p>\n<h2>Sihirbaz Nedir ve Neden Kullan\u0131l\u0131r?<\/h2>\n<p>Bir sihirbaz, genellikle karma\u015f\u0131k veya uzun bir g\u00f6revi, y\u00f6netilebilir, mant\u0131ksal ad\u0131mlara b\u00f6len bir kullan\u0131c\u0131 aray\u00fcz\u00fc (UI) desenidir. Her ad\u0131m, kullan\u0131c\u0131n\u0131n belirli bir bilgi par\u00e7as\u0131n\u0131 girmesini veya bir karar\u0131 vermesini gerektirir. Bu yap\u0131, a\u015fa\u011f\u0131daki nedenlerle tercih edilir:<\/p>\n<ul>\n<li><strong>Kullan\u0131c\u0131 Dostu Deneyim:<\/strong> Karma\u015f\u0131k g\u00f6revleri daha k\u00fc\u00e7\u00fck, sindirilebilir par\u00e7alara ay\u0131rarak kullan\u0131c\u0131lar\u0131n bunalmas\u0131n\u0131 engeller ve odaklanmalar\u0131n\u0131 sa\u011flar.<\/li>\n<li><strong>Hata Oran\u0131n\u0131 Azaltma:<\/strong> Her ad\u0131mda belirli bir validasyon uygulayarak, hatal\u0131 veri giri\u015fini veya eksik bilgiyi en ba\u015ftan yakalamaya yard\u0131mc\u0131 olur.<\/li>\n<li><strong>Ad\u0131m Ad\u0131m Rehberlik:<\/strong> Kullan\u0131c\u0131ya bir s\u00fcrecin neresinde oldu\u011funu g\u00f6sterir ve sonraki ad\u0131mlar\u0131 tahmin etmesine yard\u0131mc\u0131 olur.<\/li>\n<li><strong>Veri Toplama:<\/strong> \u00d6zellikle kay\u0131t, \u00f6deme veya yap\u0131land\u0131rma gibi s\u00fcre\u00e7lerde, gerekli t\u00fcm bilgilerin d\u00fczenli bir \u015fekilde toplanmas\u0131n\u0131 sa\u011flar.<\/li>\n<\/ul>\n<p>Ancak, geleneksel sihirbaz uygulamalar\u0131nda, sihirbaz\u0131n t\u00fcm ad\u0131mlar\u0131 genellikle ilk y\u00fcklemede birlikte gelir. Bu durum, \u00f6zellikle \u00e7ok say\u0131da ad\u0131m\u0131 olan ve her ad\u0131m\u0131n kendi i\u00e7inde karma\u015f\u0131k bile\u015fenler veya b\u00fcy\u00fck veri gerektiren sihirbazlarda, uygulaman\u0131n ilk y\u00fckleme s\u00fcresini (initial load time) ve bellek kullan\u0131m\u0131n\u0131 olumsuz etkileyebilir. \u0130\u015fte bu noktada tembel y\u00fckleme devreye girer.<\/p>\n<h2>Tembel Y\u00fckleme (Lazy Loading) Nedir ve Faydalar\u0131 Nelerdir?<\/h2>\n<p>Tembel y\u00fckleme, bir uygulaman\u0131n t\u00fcm kaynaklar\u0131n\u0131 (JavaScript, CSS, g\u00f6rseller vb.) ba\u015flang\u0131\u00e7ta y\u00fcklemek yerine, yaln\u0131zca ihtiya\u00e7 duyuldu\u011funda y\u00fcklemesini sa\u011flayan bir optimizasyon tekni\u011fidir. Bu yakla\u015f\u0131m, modern web geli\u015ftirmenin temel ta\u015flar\u0131ndan biridir ve a\u015fa\u011f\u0131daki faydalar\u0131 sunar:<\/p>\n<ul>\n<li><strong>Daha H\u0131zl\u0131 \u0130lk Y\u00fckleme S\u00fcresi:<\/strong> Kullan\u0131c\u0131lar\u0131n uygulaman\u0131z\u0131n ilk g\u00f6r\u00fcn\u00fcm\u00fcn\u00fc ve etkile\u015fimini \u00e7ok daha h\u0131zl\u0131 deneyimlemesini sa\u011flar, \u00e7\u00fcnk\u00fc ba\u015flang\u0131\u00e7ta sadece kritik kaynaklar y\u00fcklenir.<\/li>\n<li><strong>Azalt\u0131lm\u0131\u015f A\u011f Trafi\u011fi:<\/strong> Sunucudan istemciye daha az veri transferi anlam\u0131na gelir, bu da \u00f6zellikle mobil kullan\u0131c\u0131lar veya s\u0131n\u0131rl\u0131 bant geni\u015fli\u011fine sahip kullan\u0131c\u0131lar i\u00e7in \u00f6nemlidir.<\/li>\n<li><strong>Daha \u0130yi Kaynak Y\u00f6netimi:<\/strong> Uygulaman\u0131n bellek ve CPU kullan\u0131m\u0131n\u0131 optimize eder. Yaln\u0131zca aktif olarak kullan\u0131lan bile\u015fenler bellekte tutulur.<\/li>\n<li><strong>Geli\u015ftirilmi\u015f Kullan\u0131c\u0131 Deneyimi:<\/strong> Daha h\u0131zl\u0131 y\u00fckleme s\u00fcreleri ve daha ak\u0131c\u0131 bir etkile\u015fim, kullan\u0131c\u0131lar\u0131n uygulaman\u0131zda kalma olas\u0131l\u0131\u011f\u0131n\u0131 art\u0131r\u0131r.<\/li>\n<li><strong>Daha K\u00fc\u00e7\u00fck Paket Boyutlar\u0131:<\/strong> Kod b\u00f6lme (code splitting) sayesinde, uygulaman\u0131n genel JavaScript paket boyutu k\u00fc\u00e7\u00fcl\u00fcr, bu da taray\u0131c\u0131n\u0131n betikleri ayr\u0131\u015ft\u0131rma ve derleme s\u00fcresini k\u0131salt\u0131r.<\/li>\n<\/ul>\n<p>Vue.js, bu tembel y\u00fckleme mekanizmalar\u0131n\u0131 son derece kolay bir \u015fekilde entegre etmemizi sa\u011flayan g\u00fc\u00e7l\u00fc \u00f6zelliklere sahiptir.<\/p>\n<h2>Vue.js&#8217;de Tembel Y\u00fckleme Mekanizmalar\u0131<\/h2>\n<p>Vue.js, bile\u015fenleri veya rotalar\u0131 tembel y\u00fcklemek i\u00e7in \u00e7e\u015fitli yerle\u015fik mekanizmalar sunar. Sihirbaz ba\u011flam\u0131nda en s\u0131k kullanaca\u011f\u0131m\u0131z iki y\u00f6ntem \u015funlard\u0131r:<\/p>\n<h3>Vue Router ile Rota Bazl\u0131 Tembel Y\u00fckleme<\/h3>\n<p>E\u011fer sihirbaz\u0131n\u0131z\u0131n her ad\u0131m\u0131 ayr\u0131 bir URL&#8217;ye kar\u015f\u0131l\u0131k geliyorsa, Vue Router&#8217;\u0131n tembel y\u00fckleme \u00f6zelli\u011fi olduk\u00e7a kullan\u0131\u015fl\u0131d\u0131r. Bu, her bir rota bile\u015feninin yaln\u0131zca ilgili rota ziyaret edildi\u011finde y\u00fcklenmesini sa\u011flar. Bu y\u00f6ntem, bir sihirbaz\u0131n ana yap\u0131s\u0131n\u0131 olu\u015fturmak i\u00e7in kullan\u0131labilir, ancak genellikle sihirbaz\u0131n <em>i\u00e7indeki<\/em> her ad\u0131m\u0131 dinamik olarak y\u00fcklemek i\u00e7in daha esnek bir yakla\u015f\u0131m aran\u0131r.<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ router\/index.js\nimport { createRouter, createWebHistory } from 'vue-router';\n\nconst routes = [\n  {\n    path: '\/',\n    name: 'home',\n    component: () => import('..\/views\/HomeView.vue') \/\/ Tembel y\u00fcklendi\n  },\n  {\n    path: '\/wizard\/step1',\n    name: 'wizard-step1',\n    component: () => import('..\/views\/WizardStep1.vue') \/\/ Tembel y\u00fcklendi\n  },\n  {\n    path: '\/wizard\/step2',\n    name: 'wizard-step2',\n    component: () => import('..\/views\/WizardStep2.vue') \/\/ Tembel y\u00fcklendi\n  },\n  \/\/ ... di\u011fer ad\u0131mlar\n];\n\nconst router = createRouter({\n  history: createWebHistory(),\n  routes\n});\n\nexport default router;\n<\/code><\/pre>\n<p>Yukar\u0131daki \u00f6rnekte, <code>component<\/code> \u00f6zelli\u011fine do\u011frudan bir bile\u015fen referans\u0131 yerine, dinamik bir <code>import()<\/code> fonksiyonu at\u0131yoruz. Bu, webpack veya Vite gibi derleyicilere bu bile\u015feni ayr\u0131 bir JavaScript paketine b\u00f6lme talimat\u0131 verir.<\/p>\n<h3><code>defineAsyncComponent<\/code> ile Bile\u015fen Bazl\u0131 Tembel Y\u00fckleme<\/h3>\n<p>Sihirbaz\u0131m\u0131z\u0131n ad\u0131mlar\u0131 genellikle ayn\u0131 URL i\u00e7inde, ancak farkl\u0131 bile\u015fenler olarak g\u00f6r\u00fcnt\u00fclenir. \u0130\u015fte bu senaryo i\u00e7in Vue 3&#8217;\u00fcn <code>defineAsyncComponent<\/code> API&#8217;si m\u00fckemmel bir \u00e7\u00f6z\u00fcmd\u00fcr. Bu fonksiyon, bir bile\u015feni e\u015fzamans\u0131z olarak y\u00fcklemek i\u00e7in kullan\u0131l\u0131r ve y\u00fckleme durumu, hata durumu gibi ek se\u00e7enekler sunar.<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ component\/Wizard.vue i\u00e7inde\nimport { defineAsyncComponent } from 'vue';\n\nconst Step1 = defineAsyncComponent(() => import('.\/WizardSteps\/Step1.vue'));\nconst Step2 = defineAsyncComponent(() => import('.\/WizardSteps\/Step2.vue'));\nconst Step3 = defineAsyncComponent({\n  loader: () => import('.\/WizardSteps\/Step3.vue'),\n  loadingComponent: import('.\/LoadingSpinner.vue'), \/\/ Y\u00fcklenirken g\u00f6sterilecek bile\u015fen\n  errorComponent: import('.\/ErrorDisplay.vue'),     \/\/ Hata olu\u015ftu\u011funda g\u00f6sterilecek bile\u015fen\n  delay: 200,                                      \/\/ Y\u00fckleme bile\u015fenini g\u00f6stermeden \u00f6nce milisaniye cinsinden gecikme\n  timeout: 3000                                    \/\/ Y\u00fckleme hatas\u0131 olarak kabul edilmeden \u00f6nce milisaniye cinsinden zaman a\u015f\u0131m\u0131\n});\n\n\/\/ ... Vue bile\u015feninizin setup veya data k\u0131sm\u0131nda bu bile\u015fenleri kullanabilirsiniz.\n<\/code><\/pre>\n<p><code>defineAsyncComponent<\/code> fonksiyonu, bir fabrika fonksiyonu (factory function) al\u0131r. Bu fonksiyon, bile\u015feni dinamik olarak i\u00e7eri aktaran bir Promise d\u00f6nd\u00fcrmelidir. Bu sayede, <code>Step1<\/code>, <code>Step2<\/code> ve <code>Step3<\/code> bile\u015fenleri yaln\u0131zca ger\u00e7ekten ihtiya\u00e7 duyuldu\u011funda (yani, ana sihirbaz bile\u015feni taraf\u0131ndan render edilmeye \u00e7al\u0131\u015f\u0131ld\u0131\u011f\u0131nda) y\u00fcklenir.<\/p>\n<h2>Tembel Y\u00fcklenen Bir Sihirbaz Tasar\u0131m\u0131n\u0131n Temel Bile\u015fenleri<\/h2>\n<p>Tembel y\u00fcklenen bir sihirbaz olu\u015fturmak i\u00e7in a\u015fa\u011f\u0131daki temel bile\u015fenlere ihtiyac\u0131m\u0131z olacak:<\/p>\n<h3>Ana Sihirbaz Bile\u015feni (<code>WizardContainer.vue<\/code>)<\/h3>\n<p>Bu bile\u015fen, sihirbaz\u0131n kalbini olu\u015fturur. G\u00f6revleri \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>Durum Y\u00f6netimi:<\/strong> Mevcut ad\u0131m\u0131, sihirbaz\u0131n genel verilerini ve tamamlanan ad\u0131mlar\u0131 y\u00f6netir.<\/li>\n<li><strong>Navigasyon Mant\u0131\u011f\u0131:<\/strong> &#8220;\u0130leri&#8221; ve &#8220;Geri&#8221; d\u00fc\u011fmelerinin i\u015flevselli\u011fini sa\u011flar, ad\u0131mlar aras\u0131nda ge\u00e7i\u015fi kontrol eder.<\/li>\n<li><strong>Dinamik Bile\u015fen Render Etme:<\/strong> Mevcut ad\u0131ma g\u00f6re ilgili ad\u0131m bile\u015fenini dinamik olarak y\u00fckler ve render eder.<\/li>\n<li><strong>Veri Ak\u0131\u015f\u0131:<\/strong> Ad\u0131m bile\u015fenlerinden gelen veriyi toplar ve bir sonraki ad\u0131ma iletir.<\/li>\n<\/ul>\n<h3>Ad\u0131m Bile\u015fenleri (<code>WizardStep1.vue<\/code>, <code>WizardStep2.vue<\/code>, vb.)<\/h3>\n<p>Her bir ad\u0131m, kendi \u00f6zel i\u00e7eri\u011fini (form elemanlar\u0131, metinler, g\u00f6rseller) bar\u0131nd\u0131ran ayr\u0131 bir Vue bile\u015feni olacakt\u0131r. Bu bile\u015fenlerin g\u00f6revleri \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>Form Elemanlar\u0131:<\/strong> Kullan\u0131c\u0131dan bilgi toplamak i\u00e7in gerekli input, select, textarea vb. elemanlar\u0131 i\u00e7erir.<\/li>\n<li><strong>Yerel Durum:<\/strong> Kendi i\u00e7indeki form verilerini y\u00f6netir.<\/li>\n<li><strong>Validasyon:<\/strong> Ad\u0131m\u0131n gerektirdi\u011fi validasyon kurallar\u0131n\u0131 uygular.<\/li>\n<li><strong>Veri Aktar\u0131m\u0131:<\/strong> Toplad\u0131\u011f\u0131 veya g\u00fcncelledi\u011fi veriyi ana sihirbaz bile\u015fenine (genellikle <code>emit<\/code> olaylar\u0131 arac\u0131l\u0131\u011f\u0131yla) geri iletir.<\/li>\n<\/ul>\n<h3>Navigasyon Bile\u015feni (<code>WizardNavigation.vue<\/code> &#8211; Opsiyonel)<\/h3>\n<p>Bu bile\u015fen, sihirbaz\u0131n \u00fcst veya alt k\u0131sm\u0131nda yer alarak kullan\u0131c\u0131n\u0131n ad\u0131mlar aras\u0131nda gezinmesini sa\u011flar. G\u00f6revleri \u015funlard\u0131r:<\/p>\n<ul>\n<li><strong>Ad\u0131m G\u00f6stergeleri:<\/strong> Kullan\u0131c\u0131ya mevcut ad\u0131m\u0131 ve sihirbaz\u0131n toplam ad\u0131m say\u0131s\u0131n\u0131 g\u00f6sterir (\u00f6rne\u011fin, &#8220;Ad\u0131m 3 \/ 5&#8221;).<\/li>\n<li><strong>\u0130leri\/Geri D\u00fc\u011fmeleri:<\/strong> Ana sihirbaz bile\u015fenindeki navigasyon metodlar\u0131n\u0131 tetikler.<\/li>\n<li><strong>Durum Bazl\u0131 D\u00fc\u011fme Etkinle\u015ftirme:<\/strong> Ge\u00e7erli ad\u0131m\u0131n validasyon durumuna g\u00f6re &#8220;\u0130leri&#8221; d\u00fc\u011fmesini etkinle\u015ftirir veya devre d\u0131\u015f\u0131 b\u0131rak\u0131r.<\/li>\n<\/ul>\n<h2>Uygulama Ad\u0131mlar\u0131: Vue.js&#8217;de Tembel Y\u00fcklenen Sihirbaz Olu\u015fturma<\/h2>\n<p>\u015eimdi, yukar\u0131da bahsetti\u011fimiz bile\u015fenleri kullanarak pratik bir uygulama olu\u015ftural\u0131m.<\/p>\n<h3>Proje Kurulumu<\/h3>\n<p>\u00d6ncelikle, Vue CLI veya Vite kullanarak yeni bir Vue projesi olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-bash\">\n<h2>Vue CLI ile<\/h2>\nvue create my-lazy-wizard\ncd my-lazy-wizard\n\n<h2>Vite ile (daha h\u0131zl\u0131)<\/h2>\nnpm init vue@latest\ncd my-lazy-wizard\nnpm install\n<\/code><\/pre>\n<h3>Sihirbaz Veri Modeli ve Durum Y\u00f6netimi<\/h3>\n<p>Sihirbaz\u0131m\u0131z, kullan\u0131c\u0131dan \u00e7e\u015fitli bilgiler toplayacak. Bu verileri y\u00f6netmek i\u00e7in merkezi bir duruma ihtiyac\u0131m\u0131z var. K\u00fc\u00e7\u00fck bir sihirbaz i\u00e7in Vue&#8217;nun <code>reactive<\/code> veya <code>ref<\/code> API&#8217;leri yeterli olabilirken, daha karma\u015f\u0131k senaryolar i\u00e7in Pinia veya Vuex gibi bir durum y\u00f6netimi k\u00fct\u00fcphanesi tercih edilebilir. Bu \u00f6rnekte, <code>reactive<\/code> kullanarak basit bir merkezi durum olu\u015ftural\u0131m.<\/p>\n<pre><code class=\"language-javascript\">\n\/\/ src\/stores\/wizardStore.js (Basit bir merkezi durum)\nimport { reactive } from 'vue';\n\nexport const wizardStore = reactive({\n  currentStep: 1,\n  totalSteps: 3, \/\/ \u00d6rnek i\u00e7in 3 ad\u0131m\n  wizardData: {\n    personalInfo: {\n      name: '',\n      email: ''\n    },\n    addressInfo: {\n      street: '',\n      city: ''\n    },\n    paymentInfo: {\n      cardNumber: '',\n      expiryDate: ''\n    }\n  },\n  \/\/ Ad\u0131m bazl\u0131 validasyon durumlar\u0131\n  stepValidity: {\n    1: false,\n    2: false,\n    3: false\n  }\n});\n<\/code><\/pre>\n<h3>Ana Sihirbaz Bile\u015feni (<code>Wizard.vue<\/code>)<\/h3>\n<p>Bu bile\u015fen, sihirbaz\u0131m\u0131z\u0131n iskeletini olu\u015fturacak. Ad\u0131m bile\u015fenlerini dinamik olarak y\u00fckleyecek ve aralar\u0131ndaki ge\u00e7i\u015fi y\u00f6netecek.<\/p>\n<pre><code class=\"language-vue\">\n<!-- src\/components\/Wizard.vue -->\n<template>\n  <div class=\"wizard-container\">\n    <h2>Sihirbaz - Ad\u0131m {{ wizardStore.currentStep }} \/ {{ wizardStore.totalSteps }}<\/h2>\n    <div class=\"step-indicator\">\n      <span v-for=\"step in wizardStore.totalSteps\" :key=\"step\"\n            :class=\"{ &#039;active&#039;: step === wizardStore.currentStep, &#039;completed&#039;: step < wizardStore.currentStep }\">\n        {{ step }}\n      <\/span>\n    <\/div>\n\n    <div class=\"wizard-content\">\n      <!-- Dinamik ve tembel y\u00fcklenen bile\u015fen burada render edilecek -->\n      <component :is=\"currentStepComponent\"\n                 :initial-data=\"wizardStore.wizardData[stepDataKey]\"\n                 @update:data=\"updateStepData\"\n                 @update:validity=\"updateStepValidity\" \/>\n    <\/div>\n\n    <div class=\"wizard-navigation\">\n      <button @click=\"prevStep\" :disabled=\"wizardStore.currentStep === 1\">Geri<\/button>\n      <button @click=\"nextStep\" :disabled=\"!wizardStore.stepValidity[wizardStore.currentStep]\" v-if=\"wizardStore.currentStep < wizardStore.totalSteps\">\u0130leri<\/button>\n      <button @click=\"finishWizard\" :disabled=\"!isWizardValid\" v-else>Bitir<\/button>\n    <\/div>\n  <\/div>\n<\/template>\n\n<script setup>\nimport { computed, defineAsyncComponent } from 'vue';\nimport { wizardStore } from '..\/stores\/wizardStore';\n\n\/\/ Ad\u0131m bile\u015fenlerini tembel y\u00fckle\nconst Step1 = defineAsyncComponent({\n  loader: () => import('.\/WizardSteps\/Step1.vue'),\n  loadingComponent: import('.\/LoadingSpinner.vue'), \/\/ Opsiyonel\n  errorComponent: import('.\/ErrorDisplay.vue'),     \/\/ Opsiyonel\n  delay: 200\n});\nconst Step2 = defineAsyncComponent({\n  loader: () => import('.\/WizardSteps\/Step2.vue'),\n  loadingComponent: import('.\/LoadingSpinner.vue'),\n  errorComponent: import('.\/ErrorDisplay.vue'),\n  delay: 200\n});\nconst Step3 = defineAsyncComponent({\n  loader: () => import('.\/WizardSteps\/Step3.vue'),\n  loadingComponent: import('.\/LoadingSpinner.vue'),\n  errorComponent: import('.\/ErrorDisplay.vue'),\n  delay: 200\n});\n\n\/\/ Ad\u0131m bile\u015fenlerinin bir haritas\u0131\nconst stepComponents = {\n  1: Step1,\n  2: Step2,\n  3: Step3,\n};\n\n\/\/ Mevcut ad\u0131m\u0131n anahtar\u0131n\u0131 belirle (wizardData objesindeki kar\u015f\u0131l\u0131\u011f\u0131)\nconst stepDataKeys = {\n  1: 'personalInfo',\n  2: 'addressInfo',\n  3: 'paymentInfo',\n};\n\n\/\/ Mevcut ad\u0131m bile\u015fenini dinamik olarak d\u00f6nd\u00fcren computed property\nconst currentStepComponent = computed(() => {\n  return stepComponents[wizardStore.currentStep];\n});\n\n\/\/ Mevcut ad\u0131m\u0131n verisinin wizardData i\u00e7indeki anahtar\u0131n\u0131 d\u00f6nd\u00fcr\u00fcr\nconst stepDataKey = computed(() => {\n  return stepDataKeys[wizardStore.currentStep];\n});\n\n\/\/ T\u00fcm sihirbaz\u0131n ge\u00e7erli olup olmad\u0131\u011f\u0131n\u0131 kontrol eder\nconst isWizardValid = computed(() => {\n  return Object.values(wizardStore.stepValidity).every(isValid => isValid);\n});\n\n\/\/ Ad\u0131m bile\u015feninden gelen veriyi g\u00fcnceller\nconst updateStepData = (data) => {\n  wizardStore.wizardData[stepDataKey.value] = { ...wizardStore.wizardData[stepDataKey.value], ...data };\n};\n\n\/\/ Ad\u0131m bile\u015feninden gelen validasyon durumunu g\u00fcnceller\nconst updateStepValidity = (isValid) => {\n  wizardStore.stepValidity[wizardStore.currentStep] = isValid;\n};\n\n\/\/ Bir sonraki ad\u0131ma ge\u00e7\nconst nextStep = () => {\n  if (wizardStore.currentStep < wizardStore.totalSteps &#038;&#038; wizardStore.stepValidity[wizardStore.currentStep]) {\n    wizardStore.currentStep++;\n  }\n};\n\n\/\/ Bir \u00f6nceki ad\u0131ma ge\u00e7\nconst prevStep = () => {\n  if (wizardStore.currentStep > 1) {\n    wizardStore.currentStep--;\n  }\n};\n\n\/\/ Sihirbaz\u0131 bitir\nconst finishWizard = () => {\n  if (isWizardValid.value) {\n    console.log('Sihirbaz tamamland\u0131! Toplanan Veriler:', wizardStore.wizardData);\n    alert('Sihirbaz ba\u015far\u0131yla tamamland\u0131!');\n    \/\/ Verileri sunucuya g\u00f6nderme veya ba\u015fka bir i\u015flem yapma\n  } else {\n    alert('L\u00fctfen t\u00fcm ad\u0131mlar\u0131 do\u011fru \u015fekilde doldurun.');\n  }\n};\n<\/script>\n\n<style scoped>\n.wizard-container {\n  max-width: 800px;\n  margin: 50px auto;\n  padding: 20px;\n  border: 1px solid #eee;\n  border-radius: 8px;\n  box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n  font-family: Arial, sans-serif;\n}\nh2 {\n  text-align: center;\n  color: #333;\n  margin-bottom: 30px;\n}\n.step-indicator {\n  display: flex;\n  justify-content: center;\n  margin-bottom: 30px;\n}\n.step-indicator span {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 40px;\n  height: 40px;\n  border-radius: 50%;\n  background-color: #f0f0f0;\n  color: #888;\n  font-weight: bold;\n  margin: 0 10px;\n  transition: all 0.3s ease;\n}\n.step-indicator span.active {\n  background-color: #007bff;\n  color: white;\n  box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.5);\n}\n.step-indicator span.completed {\n  background-color: #28a745;\n  color: white;\n}\n.wizard-content {\n  min-height: 200px; \/<em> \u0130\u00e7erik y\u00fcklenirken yer tutmas\u0131 i\u00e7in <\/em>\/\n  margin-bottom: 30px;\n  padding: 20px;\n  border: 1px dashed #ccc;\n  border-radius: 5px;\n}\n.wizard-navigation {\n  display: flex;\n  justify-content: space-between;\n}\n.wizard-navigation button {\n  padding: 10px 20px;\n  border: none;\n  border-radius: 5px;\n  background-color: #007bff;\n  color: white;\n  cursor: pointer;\n  font-size: 16px;\n  transition: background-color 0.3s ease;\n}\n.wizard-navigation button:disabled {\n  background-color: #cccccc;\n  cursor: not-allowed;\n}\n.wizard-navigation button:hover:not(:disabled) {\n  background-color: #0056b3;\n}\n<\/style>\n<\/code><\/pre>\n<p>Yukar\u0131daki kodda dikkat edilmesi gereken noktalar:<\/p>\n<ul>\n<li><code>defineAsyncComponent<\/code> kullan\u0131larak her ad\u0131m bile\u015feni tembel y\u00fckleniyor.<\/li>\n<li><code><component :is=\"currentStepComponent\" \/><\/code> yap\u0131s\u0131, <code>currentStepComponent<\/code> computed property&#8217;sinin d\u00f6nd\u00fcrd\u00fc\u011f\u00fc bile\u015feni dinamik olarak render ediyor.<\/li>\n<li><code>initial-data<\/code> prop&#8217;u ile mevcut ad\u0131m\u0131n verileri ad\u0131m bile\u015fenine iletiliyor.<\/li>\n<li><code>@update:data<\/code> ve <code>@update:validity<\/code> olaylar\u0131 ile ad\u0131m bile\u015fenlerinden gelen veri ve validasyon durumu g\u00fcncelleniyor.<\/li>\n<li>Navigasyon butonlar\u0131, mevcut ad\u0131ma ve ad\u0131m\u0131n validasyon durumuna g\u00f6re etkinle\u015ftirilip devre d\u0131\u015f\u0131 b\u0131rak\u0131l\u0131yor.<\/li>\n<\/ul>\n<h3>Ad\u0131m Bile\u015fenlerinin Olu\u015fturulmas\u0131 (<code>Step1.vue<\/code>, <code>Step2.vue<\/code>, vb.)<\/h3>\n<p>Her bir ad\u0131m, kendi form elemanlar\u0131n\u0131 ve validasyon mant\u0131\u011f\u0131n\u0131 i\u00e7erecek. \u00d6rnek olarak <code>Step1.vue<\/code> bile\u015fenini olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-vue\">\n<!-- src\/components\/WizardSteps\/Step1.vue -->\n<template>\n  <div class=\"wizard-step\">\n    <h3>Ki\u015fisel Bilgiler<\/h3>\n    <form @submit.prevent>\n      <div class=\"form-group\">\n        <label for=\"name\">Ad\u0131n\u0131z:<\/label>\n        <input type=\"text\" id=\"name\" v-model=\"formData.name\" @input=\"validateAndEmit\" \/>\n        <p v-if=\"errors.name\" class=\"error-message\">{{ errors.name }}<\/p>\n      <\/div>\n      <div class=\"form-group\">\n        <label for=\"email\">E-posta Adresiniz:<\/label>\n        <input type=\"email\" id=\"email\" v-model=\"formData.email\" @input=\"validateAndEmit\" \/>\n        <p v-if=\"errors.email\" class=\"error-message\">{{ errors.email }}<\/p>\n      <\/div>\n    <\/form>\n  <\/div>\n<\/template>\n\n<script setup>\nimport { reactive, watch, defineProps, defineEmits } from 'vue';\n\nconst props = defineProps({\n  initialData: {\n    type: Object,\n    default: () => ({ name: '', email: '' })\n  }\n});\n\nconst emit = defineEmits(['update:data', 'update:validity']);\n\nconst formData = reactive({\n  name: props.initialData.name,\n  email: props.initialData.email\n});\n\nconst errors = reactive({\n  name: '',\n  email: ''\n});\n\n\/\/ Ad\u0131m bazl\u0131 validasyon\nconst validate = () => {\n  let isValid = true;\n  errors.name = '';\n  errors.email = '';\n\n  if (!formData.name.trim()) {\n    errors.name = 'Ad alan\u0131 bo\u015f b\u0131rak\u0131lamaz.';\n    isValid = false;\n  }\n  if (!formData.email.trim()) {\n    errors.email = 'E-posta alan\u0131 bo\u015f b\u0131rak\u0131lamaz.';\n    isValid = false;\n  } else if (!\/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$\/.test(formData.email)) {\n    errors.email = 'Ge\u00e7erli bir e-posta adresi giriniz.';\n    isValid = false;\n  }\n  return isValid;\n};\n\n\/\/ Veri de\u011fi\u015fti\u011finde ve ba\u015flang\u0131\u00e7ta validasyonu tetikle ve parent'a bildir\nconst validateAndEmit = () => {\n  const isValid = validate();\n  emit('update:data', { ...formData });\n  emit('update:validity', isValid);\n};\n\n\/\/ initialData de\u011fi\u015fti\u011finde formData'y\u0131 g\u00fcncelle (geri tu\u015funa bas\u0131ld\u0131\u011f\u0131nda \u00f6nceki veriyi y\u00fcklemek i\u00e7in)\nwatch(() => props.initialData, (newVal) => {\n  formData.name = newVal.name;\n  formData.email = newVal.email;\n  validateAndEmit(); \/\/ Veri g\u00fcncellendi\u011finde validasyonu tekrar \u00e7al\u0131\u015ft\u0131r\n}, { immediate: true }); \/\/ Bile\u015fen ilk y\u00fcklendi\u011finde de \u00e7al\u0131\u015ft\u0131r\n\n<\/script>\n\n<style scoped>\n.wizard-step {\n  padding: 20px;\n  border: 1px solid #f0f0f0;\n  border-radius: 5px;\n  background-color: #fff;\n}\nh3 {\n  color: #333;\n  margin-bottom: 20px;\n}\n.form-group {\n  margin-bottom: 15px;\n}\nlabel {\n  display: block;\n  margin-bottom: 5px;\n  font-weight: bold;\n  color: #555;\n}\ninput[type=\"text\"],\ninput[type=\"email\"] {\n  width: 100%;\n  padding: 10px;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  box-sizing: border-box;\n  font-size: 16px;\n}\ninput[type=\"text\"]:focus,\ninput[type=\"email\"]:focus {\n  border-color: #007bff;\n  outline: none;\n  box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);\n}\n.error-message {\n  color: #dc3545;\n  font-size: 14px;\n  margin-top: 5px;\n}\n<\/style>\n<\/code><\/pre>\n<p>Di\u011fer ad\u0131m bile\u015fenleri (<code>Step2.vue<\/code>, <code>Step3.vue<\/code>) de benzer bir yap\u0131y\u0131 takip edecektir, sadece i\u00e7erdikleri form elemanlar\u0131 ve validasyon mant\u0131\u011f\u0131 farkl\u0131 olacakt\u0131r.<\/p>\n<p><strong><code>LoadingSpinner.vue<\/code> (Opsiyonel Y\u00fckleme Bile\u015feni):<\/strong><\/p>\n<pre><code class=\"language-vue\">\n<!-- src\/components\/LoadingSpinner.vue -->\n<template>\n  <div class=\"loading-spinner\">\n    <div class=\"spinner\"><\/div>\n    <p>Y\u00fckleniyor...<\/p>\n  <\/div>\n<\/template>\n\n<style scoped>\n.loading-spinner {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  min-height: 100px; \/<em> Yer tutmas\u0131 i\u00e7in <\/em>\/\n}\n.spinner {\n  border: 4px solid rgba(0, 0, 0, 0.1);\n  border-left-color: #007bff;\n  border-radius: 50%;\n  width: 30px;\n  height: 30px;\n  animation: spin 1s linear infinite;\n  margin-bottom: 10px;\n}\n@keyframes spin {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n<\/style>\n<\/code><\/pre>\n<p><strong><code>ErrorDisplay.vue<\/code> (Opsiyonel Hata Bile\u015feni):<\/strong><\/p>\n<pre><code class=\"language-vue\">\n<!-- src\/components\/ErrorDisplay.vue -->\n<template>\n  <div class=\"error-display\">\n    <p>Bir hata olu\u015ftu. L\u00fctfen daha sonra tekrar deneyin.<\/p>\n    <p v-if=\"error\">{{ error.message }}<\/p>\n  <\/div>\n<\/template>\n\n<script setup>\nimport { defineProps } from 'vue';\n\ndefineProps({\n  error: Object \/\/ Hata objesi defineAsyncComponent taraf\u0131ndan sa\u011flan\u0131r\n});\n<\/script>\n\n<style scoped>\n.error-display {\n  padding: 20px;\n  border: 1px solid #dc3545;\n  background-color: #f8d7da;\n  color: #721c24;\n  border-radius: 5px;\n  text-align: center;\n}\n<\/style>\n<\/code><\/pre>\n<h3>Ana Uygulama Bile\u015feni (<code>App.vue<\/code>)<\/h3>\n<p><code>Wizard.vue<\/code> bile\u015fenini ana uygulaman\u0131zda kullanmak i\u00e7in <code>App.vue<\/code> dosyas\u0131n\u0131 g\u00fcncelleyin:<\/p>\n<pre><code class=\"language-vue\">\n<!-- src\/App.vue -->\n<template>\n  <Wizard \/>\n<\/template>\n\n<script setup>\nimport Wizard from '.\/components\/Wizard.vue';\n<\/script>\n<\/code><\/pre>\n<h3>Tembel Y\u00fcklemeyi Do\u011frulama<\/h3>\n<p>Uygulamay\u0131 \u00e7al\u0131\u015ft\u0131r\u0131n (<code>npm run dev<\/code> veya <code>yarn dev<\/code>) ve taray\u0131c\u0131n\u0131z\u0131n geli\u015ftirici ara\u00e7lar\u0131n\u0131 (Developer Tools) a\u00e7\u0131n. &#8220;Network&#8221; (A\u011f) sekmesine gidin. Sihirbaz\u0131n ilk ad\u0131m\u0131n\u0131 g\u00f6rd\u00fc\u011f\u00fcn\u00fczde, yaln\u0131zca <code>Step1.vue<\/code> bile\u015feninin JavaScript paketinin y\u00fcklendi\u011fini fark edeceksiniz. &#8220;\u0130leri&#8221; d\u00fc\u011fmesine t\u0131klad\u0131\u011f\u0131n\u0131zda ve ikinci ad\u0131ma ge\u00e7ti\u011finizde, <code>Step2.vue<\/code> bile\u015feninin paketinin e\u015fzamans\u0131z olarak y\u00fcklendi\u011fini g\u00f6receksiniz. Bu, tembel y\u00fcklemenin ba\u015far\u0131yla \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 g\u00f6sterir.<\/p>\n<h2>Geli\u015fmi\u015f Konular ve En \u0130yi Uygulamalar<\/h2>\n<h3>Validasyon Stratejileri<\/h3>\n<ul>\n<li><strong>Ad\u0131m Bazl\u0131 Validasyon:<\/strong> Her ad\u0131mda &#8220;\u0130leri&#8221; d\u00fc\u011fmesine bas\u0131ld\u0131\u011f\u0131nda o ad\u0131mdaki form alanlar\u0131n\u0131n ge\u00e7erlili\u011fini kontrol edin. Bu, kullan\u0131c\u0131n\u0131n hatalar\u0131 an\u0131nda g\u00f6rmesini ve d\u00fczeltmesini sa\u011flar.<\/li>\n<li><strong>K\u00fcresel Validasyon:<\/strong> Sihirbaz\u0131n son ad\u0131m\u0131nda, t\u00fcm sihirbaz\u0131n genel ge\u00e7erlili\u011fini kontrol edebilirsiniz. Bu, \u00f6nceki ad\u0131mlarda atlanm\u0131\u015f veya sonradan ge\u00e7ersiz hale gelmi\u015f durumlar\u0131 yakalamak i\u00e7in faydal\u0131d\u0131r.<\/li>\n<li><strong>K\u00fct\u00fcphane Kullan\u0131m\u0131:<\/strong> <a href=\"https:\/\/vee-validate.logaretm.com\/v4\/\">VeeValidate<\/a> veya <a href=\"https:\/\/vuelidate-next.netlify.app\/\">Vuelidate<\/a> gibi k\u00fct\u00fcphaneler, karma\u015f\u0131k validasyon kurallar\u0131n\u0131 daha d\u00fczenli ve s\u00fcrd\u00fcr\u00fclebilir bir \u015fekilde y\u00f6netmenize yard\u0131mc\u0131 olabilir.<\/li>\n<\/ul>\n<h3>Hata Y\u00f6netimi ve Y\u00fckleme Durumlar\u0131<\/h3>\n<p><code>defineAsyncComponent<\/code>, y\u00fckleme ve hata durumlar\u0131n\u0131 y\u00f6netmek i\u00e7in g\u00fc\u00e7l\u00fc se\u00e7enekler sunar:<\/p>\n<ul>\n<li><code>loadingComponent<\/code>: Bile\u015fen y\u00fcklenirken g\u00f6sterilecek bir bile\u015fen. Bir spinner veya &#8220;Y\u00fckleniyor&#8230;&#8221; mesaj\u0131 i\u00e7erebilir.<\/li>\n<li><code>errorComponent<\/code>: Bile\u015fenin y\u00fcklenmesi s\u0131ras\u0131nda bir hata olu\u015ftu\u011funda g\u00f6sterilecek bir bile\u015fen. Kullan\u0131c\u0131ya dost\u00e7a bir hata mesaj\u0131 sunar.<\/li>\n<li><code>delay<\/code>: <code>loadingComponent<\/code>&#8216;in g\u00f6sterilmesinden \u00f6nce beklenecek s\u00fcre (ms). K\u0131sa y\u00fcklemelerde spinner&#8217;\u0131n yan\u0131p s\u00f6nmesini engeller.<\/li>\n<li><code>timeout<\/code>: Bile\u015fenin y\u00fcklenmesi i\u00e7in maksimum s\u00fcre (ms). Bu s\u00fcrenin a\u015f\u0131lmas\u0131 durumunda <code>errorComponent<\/code> g\u00f6sterilir.<\/li>\n<\/ul>\n<p>Bu se\u00e7enekleri kullanarak kullan\u0131c\u0131ya daha bilgilendirici ve sorunsuz bir deneyim sunabilirsiniz.<\/p>\n<h3>Veri Kal\u0131c\u0131l\u0131\u011f\u0131 ve Oturum Y\u00f6netimi<\/h3>\n<p>Kullan\u0131c\u0131lar sihirbaz\u0131 tamamlarken taray\u0131c\u0131y\u0131 kapatabilir veya sayfay\u0131 yenileyebilir. Bu gibi durumlarda veri kayb\u0131n\u0131 \u00f6nlemek i\u00e7in:<\/p>\n<ul>\n<li><strong><code>localStorage<\/code>\/<code>sessionStorage<\/code>:<\/strong> Her ad\u0131m tamamland\u0131\u011f\u0131nda veya veri g\u00fcncellendi\u011finde, sihirbaz verilerini yerel depolamaya kaydedebilirsiniz. Uygulama y\u00fcklendi\u011finde bu verileri geri y\u00fckleyebilirsiniz.<\/li>\n<li><strong>API&#8217;ye Ara Kaydetme:<\/strong> \u00d6zellikle uzun ve kritik sihirbazlarda, her ad\u0131m tamamland\u0131\u011f\u0131nda verileri bir API&#8217;ye g\u00f6ndererek sunucu taraf\u0131nda kaydetmek daha g\u00fcvenli bir yakla\u015f\u0131md\u0131r.<\/li>\n<\/ul>\n<h3>Animasyonlar ve Ge\u00e7i\u015fler<\/h3>\n<p>Ad\u0131mlar aras\u0131nda daha ak\u0131c\u0131 bir ge\u00e7i\u015f sa\u011flamak i\u00e7in Vue&#8217;nun <code><Transition><\/code> bile\u015fenini kullanabilirsiniz. Bu, bir ad\u0131mdan di\u011ferine ge\u00e7erken bile\u015fenlerin kaybolup g\u00f6r\u00fcnmesi veya kayarak gelmesi gibi g\u00f6rsel efektler eklemenizi sa\u011flar.<\/p>\n<pre><code class=\"language-vue\">\n<!-- Wizard.vue i\u00e7inde -->\n<Transition name=\"fade\" mode=\"out-in\">\n  <component :is=\"currentStepComponent\"\n             :initial-data=\"wizardStore.wizardData[stepDataKey]\"\n             @update:data=\"updateStepData\"\n             @update:validity=\"updateStepValidity\"\n             :key=\"wizardStore.currentStep\" \/> <!-- Key, transition&#039;\u0131 tetiklemek i\u00e7in \u00f6nemli -->\n<\/Transition>\n\n<style>\n.fade-enter-active,\n.fade-leave-active {\n  transition: opacity 0.5s ease;\n}\n.fade-enter-from,\n.fade-leave-to {\n  opacity: 0;\n}\n<\/style>\n<\/code><\/pre>\n<h3>SEO ve Eri\u015filebilirlik (Accessibility)<\/h3>\n<ul>\n<li><strong>Anlamsal HTML:<\/strong> Form elemanlar\u0131n\u0131 do\u011fru HTML etiketleriyle (<code><br \/>\n<form><\/code>, <code><label><\/code>, <code><input><\/code> vb.) olu\u015fturun.<\/li>\n<li><strong>ARIA Etiketleri:<\/strong> \u00d6zellikle dinamik olarak de\u011fi\u015fen i\u00e7erikler i\u00e7in ARIA (Accessible Rich Internet Applications) etiketlerini kullanarak ekran okuyucular\u0131n sihirbaz\u0131n durumunu anlamas\u0131na yard\u0131mc\u0131 olun. \u00d6rne\u011fin, mevcut ad\u0131m i\u00e7in <code>aria-current=\"step\"<\/code> kullan\u0131labilir.<\/li>\n<li><strong>Klavye Navigasyonu:<\/strong> Sihirbaz\u0131n sadece fare ile de\u011fil, klavye ile de tamamen gezilebilir oldu\u011fundan emin olun (Tab, Enter tu\u015flar\u0131).<\/li>\n<\/ul>\n<h2>Sonu\u00e7<\/h2>\n<p>Vue.js&#8217;de tembel y\u00fcklenen bir sihirbaz olu\u015fturmak, modern web uygulamalar\u0131nda performans ve kullan\u0131c\u0131 deneyimi a\u00e7\u0131s\u0131ndan \u00f6nemli avantajlar sunar. <code>defineAsyncComponent<\/code> gibi Vue&#8217;nun g\u00fc\u00e7l\u00fc API&#8217;leri sayesinde, karma\u015f\u0131k i\u015f ak\u0131\u015flar\u0131n\u0131 daha k\u00fc\u00e7\u00fck, y\u00f6netilebilir ve yaln\u0131zca ihtiya\u00e7 duyuldu\u011funda y\u00fcklenen par\u00e7alara ay\u0131rmak olduk\u00e7a kolayd\u0131r.<\/p>\n<p>Bu yakla\u015f\u0131m, uygulaman\u0131z\u0131n ilk y\u00fckleme s\u00fcresini k\u0131salt\u0131r, a\u011f trafi\u011fini azalt\u0131r ve bellek kullan\u0131m\u0131n\u0131 optimize eder. Ayr\u0131ca, kullan\u0131c\u0131lar\u0131n sihirbazla daha ak\u0131c\u0131 ve tepkisel bir \u015fekilde etkile\u015fim kurmas\u0131n\u0131 sa\u011flar. Do\u011fru durum y\u00f6netimi, validasyon, hata y\u00f6netimi ve eri\u015filebilirlik uygulamalar\u0131yla birle\u015fti\u011finde, tembel y\u00fcklenen bir Vue.js sihirbaz\u0131, hem geli\u015ftiriciler hem de son kullan\u0131c\u0131lar i\u00e7in \u00fcst\u00fcn bir deneyim sunar.<\/p>\n<p>Bu makalede sunulan ad\u0131mlar ve kod \u00f6rnekleri, kendi tembel y\u00fcklenen sihirbaz\u0131n\u0131z\u0131 olu\u015fturman\u0131z i\u00e7in sa\u011flam bir temel sa\u011flamaktad\u0131r. Uygulaman\u0131z\u0131n \u00f6zel ihtiya\u00e7lar\u0131na g\u00f6re bu yap\u0131y\u0131 geni\u015fletebilir ve \u00f6zelle\u015ftirebilirsiniz. Unutmay\u0131n, performans optimizasyonu ve iyi bir kullan\u0131c\u0131 deneyimi, s\u00fcrekli bir iyile\u015ftirme s\u00fcrecidir.<\/p>\n<p><\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma\nModern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini (UX) \u00f6n planda tutarak h\u0131zl\u0131, a","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1402],"tags":[],"class_list":{"0":"post-37764","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-vue","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Vue.js&#039;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Vue.js&#039;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma\" \/>\n<meta property=\"og:description\" content=\"Vue.js&#039;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma Modern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini (UX) \u00f6n planda tutarak h\u0131zl\u0131, a\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-14T16:41:03+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma\",\"datePublished\":\"2026-01-14T16:41:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\"},\"wordCount\":2234,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Vue\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\",\"name\":\"Vue.js'de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-01-14T16:41:03+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Vue.js'de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/","og_locale":"tr_TR","og_type":"article","og_title":"Vue.js'de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma","og_description":"Vue.js'de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma Modern web uygulamalar\u0131, kullan\u0131c\u0131 deneyimini (UX) \u00f6n planda tutarak h\u0131zl\u0131, a","og_url":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-01-14T16:41:03+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"13 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma","datePublished":"2026-01-14T16:41:03+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/"},"wordCount":2234,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Vue"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/","url":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/","name":"Vue.js'de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-01-14T16:41:03+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/vue-jsde-tembel-yuklenen-lazy-loaded-bir-sihirbaz-olusturma\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Vue.js&#8217;de Tembel Y\u00fcklenen (Lazy Loaded) Bir Sihirbaz Olu\u015fturma"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/37764","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=37764"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/37764\/revisions"}],"predecessor-version":[{"id":37765,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/37764\/revisions\/37765"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=37764"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=37764"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=37764"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}