İş uygulamaları için Vue 3 form mimarisi: yeniden kullanılabilir desenler
İş uygulamaları için Vue 3 form mimarisi: yeniden kullanılabilir alan bileşenleri, anlaşılır doğrulama kuralları ve sunucu hatalarını her inputa göstermek için pratik yollar.

Neden form kodu gerçek iş uygulamalarında çöker?
Bir iş uygulamasındaki form nadiren küçük kalır. "Sadece birkaç input" olarak başlar, sonra onlarca alana, koşullu bölümlere, izinlere ve backend mantığıyla uyumlu kalması gereken kurallara dönüşür. Birkaç ürün değişikliğinden sonra form çalışmaya devam eder, ama kod kırılgan hissettirir.
Vue 3 form mimarisi önemlidir çünkü formlar "hızlı düzeltmeler"in biriktiği yerdir: bir watcher daha, bir tane özel durum daha, bir bileşenin kopyalanması daha. Bugün çalışır, ama güvenmesi ve değiştirmesi zorlaşır.
Uyarı işaretleri tanıdıktır: sayfalar boyunca tekrar eden input davranışları (etiketler, biçimlendirme, zorunlu işaretleri, ipuçları), tutarsız hata yerleştirme, doğrulama kurallarının bileşenlere dağılması ve backend hatalarının kullanıcıya neyi düzeltmeleri gerektiğini söylemeyen genel bir toast'a indirgenmesi.
Bu tutarsızlıklar sadece kod stili sorunları değildir. UX sorunlarına dönüşür: kullanıcılar formları tekrar gönderir, destek talepleri artar ve ekipler formlara dokunmaktan kaçınır çünkü gizli bir uç durumda bir şeyler kırılabilir.
İyi bir kurulum, formları en iyi anlamda sıkıcı yapar. Öngörülebilir bir yapı ile alan ekleyebilir, kuralları değiştirebilir ve sunucu yanıtlarını her şeyi yeniden kabloya bağlamadan ele alabilirsiniz.
İstediğiniz şey tekrar kullanım (bir alan her yerde aynı davranır), açıklık (kurallar ve hata işlemleri kolayca incelenir), öngörülebilir davranış (touched, dirty, reset, submit) ve daha iyi geri bildirim (sunucu tarafı hatalar dikkat gerektiren girdilerde görünür). Aşağıdaki desenler yeniden kullanılabilir alan bileşenlerine, okunabilir doğrulamaya ve sunucu hatalarını belirli girdilere eşlemeye odaklanır.
Form yapısı için basit bir zihinsel model
Zamana karşı dayanan bir form, bir dizi açık parçaya sahip küçük bir sistemdir, rastgele input yığını değil.
Birbirine tek yönlü konuşan dört katmanı düşünün: UI girdi toplar, form durumu bunu saklar, doğrulama neyin yanlış olduğunu açıklar ve API katmanı yükler/kaydeder.
Dört katman (ve her birinin sahip olduğu şeyler)
- Field UI component: inputu, etiketi, ipucunu ve hata metnini render eder. Değer değişikliklerini yayınlar.
- Form state: değerleri ve hataları tutar (ayrıca touched ve dirty bayrakları).
- Validation rules: değerleri okuyan ve hata mesajları döndüren saf fonksiyonlar.
- API calls: başlangıç verisini yükler, değişiklikleri gönderir ve sunucu yanıtlarını alan hatalarına çevirir.
Bu ayrım değişiklikleri kapsüllü tutar. Yeni bir gereksinim geldiğinde, diğerlerini bozmadan bir katmanı güncellersiniz.
Bir alana ne ait, ebeveyn forma ne ait?
Yeniden kullanılabilir bir alan bileşeni sıkıcı olmalı. API'niz, veri modeliniz veya doğrulama kurallarınız hakkında bilgi sahibi olmamalı. Sadece bir değeri göstermeli ve bir hatayı göstermeli.
Ebeveyn form geri kalan her şeyi koordine eder: hangi alanların olduğu, değerlerin nerede yaşadığı, ne zaman doğrulama yapılacağı ve nasıl gönderileceği.
Basit bir kural yardımcı olur: mantık diğer alanlara bağlıysa (örneğin State yalnızca Country US olduğunda zorunluysa), bunu alan bileşeninin içine değil, ebeveyn forma veya doğrulama katmanına koyun.
Gerçekten düşük eforlu bir alan ekleme yapıyorsanız, genellikle yalnızca varsayılanları veya şemayı, alanın yerleştirildiği işaretlemeyi ve alanın doğrulama kurallarını değiştirirsiniz. Bir input eklemek alakasız bileşenlerde değişiklik yapmayı gerektiriyorsa sınırlarınız bulanıktır.
Yeniden kullanılabilir alan bileşenleri: neyi standartlaştırmalı
Formlar büyüdüğünde en hızlı kazanım her inputu tek seferlik gibi inşa etmeyi bırakmaktır. Alan bileşenleri öngörülebilir hissetmelidir. Bu onları hızlı kullanılabilir ve incelemesi kolay yapar.
Pratik bir yapı taşları seti:
- BaseField: etiket, ipucu, hata metni, boşluk ve erişilebilirlik öznitelikleri için sarmalayıcı.
- Input bileşenleri: TextInput, SelectInput, DateInput, Checkbox vb. Her biri kontrol üzerine odaklanır.
- FormSection: ilgili alanları başlık, kısa yardım metni ve tutarlı boşluk ile gruplar.
Props için küçük bir set tutun ve her yerde bunu uygulayın. 40 formda bir prop adını değiştirmek acı verir.
Genellikle hemen kazandıranlar:
modelValueveupdate:modelValueiçinv-modellabelrequireddisablederror(tek mesaj veya tercih ederseniz dizi)hint
Slotlar, uyumluluğu bozmadan esneklik tanıdığınız yerlerdir. BaseField düzenini sabit tutun, ancak sağ tarafta bir eylem ("Send code") veya başa bir ikon gibi küçük varyasyonlara izin verin. Bir varyasyon iki kez ortaya çıkarsa, bileşeni çatallamak yerine bir slot yapın.
Render sırasını standartlaştırın (etiket, kontrol, ipucu, hata). Kullanıcılar daha hızlı tarar, testler basitleşir ve sunucu hata eşlemesi kolaylaşır çünkü her alanın mesaj göstereceği tek bir yer vardır.
Form durumu: values, touched, dirty ve reset
İş uygulamalarındaki çoğu form hatası inputlarla ilgili değildir. Dağınık durumdan gelir: değerler bir yerde, hatalar başka bir yerde ve yalnızca yarısı çalışan bir reset düğmesi. Temiz bir Vue 3 form mimarisi, tek bir tutarlı durum şekliyle başlar.
Öncelikle alan anahtarları için bir isimlendirme kuralı seçin ve buna uyun. En basit kural: alan anahtarı API yükü anahtarına eşittir. Sunucunuz first_name bekliyorsa, form anahtarınız da first_name olmalı. Bu küçük seçim doğrulama, kaydetme ve sunucu hata eşlemesini çok daha kolay kılar.
Form durumunuzu tek bir yerde tutun (bir composable, bir Pinia store veya bir ebeveyn bileşen) ve her alanın o durum üzerinden okuma/yazma yapmasını sağlayın. Düz bir yapı çoğu ekran için işe yarar. Sadece API gerçekten iç içe olduğunda iç içe yapıya gidin.
const state = reactive({
values: { first_name: '', last_name: '', email: '' },
touched: { first_name: false, last_name: false, email: false },
dirty: { first_name: false, last_name: false, email: false },
errors: { first_name: '', last_name: '', email: '' },
defaults: { first_name: '', last_name: '', email: '' }
})
Bayraklar hakkında pratik bir düşünce:
touched: kullanıcı bu alanla etkileşime geçti mi?dirty: değer varsayılandan (veya son kaydedilen değerden) farklı mı?errors: şu anda kullanıcı ne görmeli?defaults: neye sıfırlıyoruz?
Reset davranışı öngörülebilir olmalı. Varolan bir kaydı yüklediğinizde, hem values hem de defaults aynı kaynaktan ayarlayın. Sonra reset() defaults'ı valuesa kopyalayabilir, touched ve dirty'yi temizleyebilir ve errors'ı sıfırlayabilir.
Örnek: bir müşteri profil formu sunucudan email yüklüyor. Kullanıcı bunu düzenlerse dirty.email true olur. Reset'e tıklarsa email yüklenen değere geri döner (boş string değil) ve ekran tekrar temiz görünür.
Okunabilir kalan doğrulama kuralları
Okunabilir doğrulama, kütüphaneden çok kuralları nasıl ifade ettiğinizle ilgilidir. Bir alana bakıp birkaç saniyede kurallarını anlayabiliyorsanız form kodunuz sürdürülebilir kalır.
Uyum sağlayabileceğiniz bir kural stilini seçin
Çoğu ekip şu yaklaşımlardan birine yerleşir:
- Alan-başına kurallar: kurallar alan kullanımına yakın yaşar. Taraması kolay, küçük ve orta formlar için harika.
- Şema-temelli kurallar: kurallar tek bir nesnede veya dosyada toplanır. Aynı modelin birçok ekranda yeniden kullanıldığı durumlarda iyidir.
- Hibrit: basit kurallar alan yakınında, paylaşılan veya karmaşık kurallar merkezi bir şemada.
Hangisini seçerseniz seçin, kural adlarını ve mesajları öngörülebilir tutun. Birkaç ortak kural (required, length, format, range) tek seferlik yardımcıların uzun listesinden iyidir.
Kuralları düz İngilizce gibi yazın (anlaşılır olun)
İyi bir kural bir cümle gibi okunur: "Email required ve email formatında olmalı." Niyetin saklandığı zeki tek satırlardan kaçının.
Çoğu iş formu için, bir seferde bir mesaj döndürmek (alan başına ilk başarısızlık) UI'yı sakin tutar ve kullanıcıların sorunları daha hızlı düzeltmesine yardımcı olur.
Kullanıcı dostu kalan yaygın kurallar:
- Required sadece kullanıcı gerçekten doldurmalıysa.
- Length gerçek sayılarla (ör. 2 ile 50 karakter arası).
- Format email, telefon, posta kodu için; gerçek girdileri reddeden aşırı katı regexlerden kaçının.
- Range ör. "tarih gelecekte olmamalı" veya "miktar 1 ile 999 arası".
Async kontrolleri belirgin yapın
"Kullanıcı adı alınmış" gibi async doğrulama, sessizce tetiklendiğinde kafa karıştırır.
Kontrolleri blur'da veya kısa bir bekleme sonrası tetikleyin, net bir "Kontrol ediliyor..." durumu gösterin ve kullanıcı yazmaya devam ettiğinde eski istekleri iptal edin veya görmezden gelin.
Doğrulamanın ne zaman çalışacağını belirleyin
Zamanlama kurallar kadar önemlidir. Kullanıcı dostu bir kurulum önerisi:
- Change üzerinde: canlı geri bildirimden fayda sağlayan alanlar için (ör. parola gücü), ama nazik olun.
- Blur üzerinde: çoğu alan için, böylece kullanıcı sürekli hatalarla karşılaşmadan yazabilir.
- Submit üzerinde: tüm form için son güvenlik ağı.
Sunucu hatalarını doğru inputa eşleme
İstemci tarafı kontroller hikayenin sadece yarısıdır. İş uygulamalarında sunucu, tarayıcının bilemeyeceği kurallar nedeniyle kaydı reddeder: çoğaltmalar, izin kontrolleri, eski veriler, durum değişiklikleri ve daha fazlası. İyi form UX, bu yanıtı doğru girdinin yanına net mesajlara dönüştürmeye bağlıdır.
Hataları tek bir dahili şekle normalleştirin
Back-end'ler nadiren aynı hata formatını kullanır. Bazıları tek bir nesne döner, bazıları listeler, bazıları alan adına göre anahtarlanmış iç içe haritalar döner. Aldığınız her şeyi formunuzun render edebileceği tek bir dahili şekle çevirin.
// what your form code consumes
{
fieldErrors: { "email": ["Already taken"], "address.street": ["Required"] },
formErrors: ["You do not have permission to edit this customer"]
}
Bir kaç kuralı tutarlı tutun:
- Alan hatalarını diziler olarak saklayın (sadece bir mesaj olsa bile).
- Farklı yol stillerini tek bir stile çevirin (nokta yolları iyi çalışır:
address.street). - Alan dışı hataları
formErrorsolarak ayrı tutun. - Ham sunucu yükünü loglama için saklayın, ama onu render etmeyin.
Sunucu yollarını form anahtarlarınızla eşleyin
Zor kısım, sunucunun "yol" kavramını formunuzun alan anahtarlarıyla hizalamaktır. Her alan bileşeni için bir anahtar (ör. email, profile.phone, contacts.0.type) belirleyin ve buna sadık kalın.
Sonra yaygın durumları işleyen küçük bir eşleyici yazın:
address.street(nokta gösterimi)address[0].street(diziler için köşeli parantez)/address/street(JSON Pointer stili)
Normalleştirmeden sonra, <Field name="address.street" /> fieldErrors["address.street"] okuyabilmelidir.
Gerekirse alias'ları destekleyin. Eğer backend customer_email döndürüyorsa ama UI email kullanıyorsa, normalleştirme sırasında { customer_email: "email" } gibi bir eşleme tutun.
Alan hataları, form seviyesinde hatalar ve odaklama
Her hata tek bir inputa ait değildir. Sunucu "Plan limiti aşıldı" veya "Ödeme gerekli" diyorsa, bunu formun üstünde form-seviyesinde gösterin.
Alan-spesifik hatalar için mesajı inputun yanında gösterin ve kullanıcıyı ilk probleme yönlendirin:
- Sunucu hatalarını ayarladıktan sonra,
fieldErrorsiçindeki formda render edilen ilk anahtarı bulun. - Görünür hale getirmek için kaydırın ve odaklayın (her alan için bir ref ve
nextTickkullanarak). - Kullanıcı o alanı tekrar düzenlediğinde alanın sunucu hatalarını temizleyin.
Adım adım: mimariyi birleştirmek
Formlar sakin kalırsa, erken karar verirsiniz: durum, UI, doğrulama ve API'ye ne ait, sonra bunları birkaç küçük fonksiyonla birbirine bağlarsınız.
Birçok iş uygulaması için işe yarayan sıra:
- Tek bir form modeli ve sabit alan anahtarlarıyla başlayın. Bu anahtarlar bileşenler, validatorler ve sunucu hataları arasında bir sözleşme olur.
- Etiket, yardımcı metin, zorunlu işareti ve hata gösterimi için bir BaseField sarmalayıcı oluşturun. Input bileşenlerini küçük ve tutarlı tutun.
- Alan başına çalıştırılabilen ve gönderme sırasında her şeyi doğrulayabilen bir doğrulama katmanı ekleyin.
- API'ye gönderin. Eğer başarısız olursa, sunucu hatalarını
{ [fieldKey]: message }formatına çevirin ki doğru input doğru mesajı göstersin. - Başarı işlemlerini ayrı tutun (reset, toast, yönlendirme) böylece bileşenlere ve doğrulayıcılara sızmaz.
Durum için basit bir başlangıç noktası:
const values = reactive({ email: '', name: '', phone: '' })
const touched = reactive({ email: false, name: false, phone: false })
const errors = reactive({}) // { email: '...', name: '...' }
BaseField'iniz label, error ve belki touched alır ve mesajı tek bir yerde render eder. Her input bileşeni sadece bağlanma ve güncellemeleri yayınlama ile ilgilenir.
Doğrulama için kuralları modelin yakınında aynı anahtarları kullanarak tutun:
const rules = {
email: v => (!v ? 'Email is required' : /@/.test(v) ? '' : 'Enter a valid email'),
name: v => (v.length < 2 ? 'Name is too short' : ''),
}
function validateAll() {
Object.keys(rules).forEach(k => {
const msg = rules[k](values[k])
if (msg) errors[k] = msg
else delete errors[k]
touched[k] = true
})
return Object.keys(errors).length === 0
}
Sunucu hatalarıyla karşılaşıldığında, onları aynı anahtarları kullanarak eşleyin. API { "field": "email", "message": "Already taken" } dönerse errors.email = 'Already taken' yapın ve touched olarak işaretleyin. Hata globalse (ör. "izin yok") formun üstünde gösterin.
Örnek senaryo: bir müşteri profilini düzenlemek
Bir destek görevlisinin bir müşteri profilini düzenlediği dahili bir yönetici ekranını hayal edin. Form dört alan içerir: name, email, phone ve role (Customer, Manager, Admin). Küçük, ama yaygın sorunları gösteriyor.
İstemci tarafı kurallar net olmalı:
- Name: zorunlu, minimum uzunluk.
- Email: zorunlu, geçerli email formatı.
- Phone: isteğe bağlı, ama doldurulursa kabul edilen formata uymalı.
- Role: zorunlu ve bazen koşullu (sadece doğru izinlere sahip kullanıcılar Admin atayabilir).
Tutarlı bir bileşen sözleşmesi yardımcı olur: her alan mevcut değeri, mevcut hata metnini (varsa) ve touched veya disabled gibi birkaç boolean alır. Etiketler, zorunlu işaretleri, boşluk ve hata stili her ekranda yeniden icat edilmemeli.
Şimdi UX akışı. Görevli emaili düzenler, tab yapar ve format yanlışsa Email altında satır içi bir mesaj görür. Düzeltir, Kaydet'e basar ve sunucu yanıt verir:
- email zaten var: Email altında gösterin ve o alanı odaklayın.
- telefon geçersiz: Phone altında gösterin.
- izin reddedildi: formun üstünde genel bir mesaj gösterin.
Hataları email, phone, role gibi alan adlarıyla anahtarlarsanız, eşleme basittir. Alan hataları inputların yanına düşer, form seviyesindeki hatalar ayrılmış bir mesaj alanına yerleştirilir.
Ortak hatalar ve nasıl önlenir
Mantığı tek bir yerde tutun
Her ekranda doğrulama kurallarını kopyalamak hızlı gelir ama politika değiştiğinde (parola kuralları, zorunlu vergi kimlikleri, izin verilen alanlar) sorun olur. Kuralları merkezileştirin (şema, kurallar dosyası, paylaşılan fonksiyon) ve formlar aynı kural setini tüketsin.
Ayrıca düşük seviyeli inputların çok fazla yapmasına izin vermeyin. Eğer <TextField> API çağırmayı, hatalar için retry yapmayı ve sunucu hata yüklerini parse etmeyi biliyorsa, yeniden kullanılabilirliği kaybeder. Alan bileşenleri render etmeli, değer değişikliklerini yayınlamalı ve hataları göstermelidir. API çağrılarını ve eşleme mantığını form konteynerinde veya bir composable'da tutun.
Kayıt belirtileri:
- Aynı doğrulama mesajı birden fazla yerde yazılmış.
- Bir alan bileşeni bir API istemcisi import ediyor.
- Bir endpoint değiştirmek alakasız birkaç formu kırıyor.
- Bir inputu test etmek için uygulamanın yarısını mount etmeniz gerekiyor.
UX ve erişilebilirlik tuzakları
"Bir şeyler yanlış gitti" gibi tek bir hata banner'ı yeterli değildir. İnsanlar hangi alanın yanlış olduğunu ve ne yapacaklarını bilmek ister. Ağır hatalar (ağ kesintisi, izin reddi) için banner'lar kullanın ve sunucu hatalarını belirli inputlara eşleyin ki kullanıcılar hızlıca düzeltebilsin.
Yükleme ve çift gönderme sorunları kafa karıştırıcı durumlar yaratır. Gönderirken submit'i devre dışı bırakın, kaydetme sırasında değişmemesi gereken alanları devre dışı bırakın ve net bir meşgul durumu gösterin. Reset ve iptalin formu temiz bir şekilde geri getirdiğinden emin olun.
Özel bileşenlerle erişilebilirlik temel kuralları atlamak kolaydır. Birkaç seçim gerçek acıları önler:
- Her inputun görünür bir etiketi olsun (sadece placeholder değil).
- Hatalar uygun aria öznitelikleri ile alanlara bağlansın.
- Gönderim sonrası ilk geçersiz alan odaklansın.
- Devre dışı bırakılmış alanlar gerçekten etkileşimsiz olsun ve doğru şekilde ilan edilsin.
- Klavye navigasyonu uçtan uca çalışsın.
Hızlı kontrol listesi ve sonraki adımlar
Yeni bir form yayınlamadan önce kısa bir kontrol listesi çalıştırın. Destek taleplerine dönüşecek küçük boşlukları yakalar.
- Her alan, payload ile ve sunucu yanıtıyla eşleşen sabit bir anahtara sahip mi (ör.
billing.address.zipgibi iç içe yollar dahil)? - Her alan aynı tutarlı alan bileşen API'siyle render edilebilir mi (değer giriş, olaylarla çıkış, hata ve ipucu giriş)?
- Gönderimde bir kere doğrulama yapıyor, çift gönderimi engelliyor ve kullanıcıların nereden başlayacağını bilmeleri için ilk geçersiz alanı odaklıyor musunuz?
- Hataları doğru yerde gösterebiliyor musunuz: alan başına (inputun yanında) ve form seviyesi (gerekli olduğunda genel mesaj)?
- Başarıdan sonra state'i doğru sıfırlıyor musunuz (values, touched, dirty) ki bir sonraki düzenleme temiz başlasın?
Eğer bir cevap "hayır" ise, önce onu düzeltin. En yaygın form ağrısı uyuşmazlıktır: alan adları API'den uzaklaşır veya sunucu hataları UI'nın yerleştiremeyeceği bir şekille geri döner.
Eğer dahili araçlar inşa ediyorsanız ve daha hızlı ilerlemek istiyorsanız, AppMaster (appmaster.io) aynı temelleri takip eder: alan UI'sini tutarlı tutun, kuralları ve iş akışlarını merkezileştirin ve sunucu yanıtlarının kullanıcıların işlem yapabileceği yerlere düşmesini sağlayın.
SSS
Sayfalar arasında aynı etiket, yardımcı metin, zorunlu işareti, boşluk ve hata stili tekrarlandığını görmeye başladığınızda bunları standartlaştırın. Küçük bir değişiklik birçok dosyayı düzenlemeyi gerektiriyorsa, paylaşılan bir BaseField sarmalayıcısı ve birkaç tutarlı input bileşeni zaman kazandırır.
Alan bileşenini "aptal" tutun: etiket, kontrol, yardımcı metin ve hatayı render eder ve değer güncellemelerini yayınlar. Alanlar arasındaki mantık, koşullu kurallar ve diğer değerlere bağlı her şey üst formda veya bir doğrulama katmanında olmalı, böylece alan yeniden kullanılabilir kalır.
Varsayılan olarak API yükünüzle eşleşen sabit anahtarlar kullanın; örneğin first_name veya billing.address.zip. Bu, doğrulamayı ve sunucu hata eşlemeyi basitleştirir çünkü katmanlar arasında isimleri sürekli çevirmek zorunda kalmazsınız.
Basit bir varsayılan, values, errors, touched, dirty ve defaults tutan tek bir durum nesnesidir. Her şey aynı yapı üzerinden okunup yazıldığında, sıfırlama ve gönderme davranışı tahmin edilebilir olur ve “yarım sıfırlama” hatalarından kaçınırsınız.
values ve defaults değerlerini aynı yüklenen veriden ayarlayın. Ardından reset() defaults içeriğini valuesa kopyalamalı ve touched, dirty ve errors öğelerini temizleyerek UI'nın sunucunun son döndürdüğüyle eşleşmesini sağlamalıdır.
Form durumuyla aynı anahtarları kullanarak basit fonksiyonlar halinde kurallar yazın. Her alana yalnızca bir açık mesaj (ilk başarısızlık) döndürmek UI'yı sakin tutar ve kullanıcıların neyi düzeltmeleri gerektiğini kolaylaştırır.
Çoğu alan için blur üzerinde doğrulama yapın, ardından gönderme sırasında her şeyi bir final kontrolü olarak doğrulayın. Sadece gerçekten yardımcı olduğu durumlarda (ör. parola güçlendirici) değişiklikte doğrulama kullanın ki kullanıcı yazarken hatalarla cezalandırılmasın.
Async kontrolleri blur veya kısa bir debounce sonrası çalıştırın ve açık bir “kontrol ediliyor” durumu gösterin. Ayrıca eski isteklerin sonuçlarının daha yeni girdileri geçersiz kılmaması için iptal edin veya yok sayın.
Her backend formatını { fieldErrors: { key: [messages] }, formErrors: [messages] } gibi tek bir dahili şekle çevirin. Nokta notasyonu gibi tek bir yol stili kullanın ki address.street adlı bir alan her zaman fieldErrors['address.street'] okuması yapabilsin.
Form seviyesindeki hataları formun üstünde gösterin; alan hatalarını ise ilgili inputun yanında gösterin. Başarısız bir gönderimden sonra, hatası olan ilk alanı odaklayın ve kullanıcı o alanı düzenledikçe sunucu hatasını temizleyin.


