modelValue ve update:modelValue
Vue’yu öğrenmeye yeni başlayan herkes v-model'i sever. Çünkü bir input’a değer bağlamak kadar kolay bir şey yoktur. Fakat perde arkasında neler döndüğünü anlamadığında, kendi bileşenlerinde v-model çalışmaz ve sihir bozulur. 🙃
Bu yazıda v-model’in nasıl çalıştığını, modelValue ve update:modelValue olaylarının aslında neyi temsil ettiğini adım adım anlatacağız.
Kısaca v-model
En temel haliyle:<input v-model="name" />
Bu, aslında Vue tarafından şuna çevrilir:<input :value="name" @input="name = $event.target.value" />
Yani v-model, bir :value binding’i ve bir @input event listener’ının kısayoludur. Ama bu sadece native HTML input’ları için geçerli. Bileşen yazdığında işler değişir. 👇Bileşenlerde v-model Nasıl Çalışır?
Vue, kendi bileşenindev-model kullanıldığında otomatik olarak iki şeyi arar:modelValueadlı bir prop,update:modelValueadlı bir emit.
<!-- Parent -->
<MyInput v-model="username" />
<!-- MyInput.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
<template>
<input :value="modelValue" @input="emit('update:modelValue', $event.target.value)" />
</template>
Artık v-model tıpkı native input’ta olduğu gibi çift yönlü çalışır: parent değeri gönderir (props), child ise değişikliği bildirir (emit).
İçeride Neler Oluyor?
v-model bir veri akışı protokolüdür. Bu protokolün iki yönü vardır:- Downstream (parent → child):
modelValueprop’u üzerinden değer akar. - Upstream (child → parent):
update:modelValueevent’iyle değişiklik bildirilir.
username değişkenini reactive olarak tutar ve bu değişken, child’daki input değerine otomatik olarak bağlanır.Yani: v-model, “props içeri, emit dışarı” kuralını iki yönlü hale getirir.
İsimlendirme Değiştirmek Mümkün
Bazı durumlarda birden fazlav-model kullanmak isteyebilirsin (örneğin biri value, biri checked için). Vue buna da izin verir.<MyToggle v-model:checked="isOn" v-model:label="title" />
<script setup>
const props = defineProps(['checked', 'label'])
const emit = defineEmits(['update:checked', 'update:label'])
</script>
Böylece her v-model farklı bir prop/event çiftiyle eşleşir.💡 İpucu: Çoklu v-model yapısı, özellikle form bileşenlerinde esneklik sağlar. Örneğin hem “value” hem “valid” state’lerini kontrol etmek için birebir.
v-model’in İçinde Gerçekte Ne Var?
Vue template derleyicisi,v-model gördüğünde bunu otomatik olarak şu pattern’e çevirir:<MyInput :modelValue="username" @update:modelValue="username = $event" />
Bu sayede senin ekstra bir kod yazmana gerek kalmaz. Ancak kendi bileşeninde defineEmits(['update:modelValue']) yazmadıysan, Vue hata verir: > Missing required emit event: update:modelValueBu yüzden v-model’in çalışması tamamen bu sözleşmeye bağlıdır.
İleri Kullanım: Computed v-model
Bazen parent’ta tuttuğun veriyi bileşen içinde biraz dönüştürmek isteyebilirsin. İşte o zaman computed setter/getter ile özel bir v-model yazılabilir:const message = ref('Hello')
const upper = computed({
get: () => message.value.toUpperCase(),
set: val => message.value = val.toLowerCase()
})
Artık v-model="upper" kullandığında, input her zaman büyük harfli görünür ama küçük harfli kaydedilir. 😎v-model Modifiers
Vue bazı modifiyer’leri de destekler (.trim, .number, .lazy gibi):<input v-model.trim.number="age" />
Bunlar aslında input event’ini sarmalayan minik transform fonksiyonlarıdır. Yani v-model.number = parseFloat($event.target.value) gibidir..lazy modifiyeri, input yerine change event’ine bağlanır; performans veya doğrulama kontrolü açısından kullanışlıdır.
Birden Fazla v-model Ne Zaman Kullanılır?
Form bileşenlerinde aynı anda birden çok state’i (örneğinvalue, error, valid) yönetmek için:<MyField v-model:value="text" v-model:valid="isValid" />
Bu yaklaşım, form doğrulama kütüphanelerinde standart haline gelmiştir. Her biri bağımsız bir veri akışını temsil eder.Gerçek Hayat Örneği
Basit bir modal bileşeni düşünelim:<Modal v-model:open="isOpen" />
Child:<script setup>
const props = defineProps(['open'])
const emit = defineEmits(['update:open'])
function close(){ emit('update:open', false) }
</script>
Artık parent’ta isOpen = false olduğunda modal kapanır, modal içinden kapatıldığında da parent state güncellenir. İki yönlü kontrol tamam.Yaygın Hatalar
defineEmits(['update:modelValue'])yazmayı unutmak.v-modelyerine hem:modelValuehem@update:modelValuemanuel yazmak (gereksizdir).- Props’u doğrudan değiştirmeye çalışmak (
props.modelValue = 'x') -- bu Vue’da readonly hatasına neden olur. v-modelkullanırken destructuring ile props’u koparmak (const { modelValue } = props) reaktiviteyi bozar.
Özet Tablo
| Terim | Anlamı |
|---|---|
v-model | İki yönlü binding kısayolu |
modelValue | Parent’tan gelen veri |
update:modelValue | Child’dan dışarı event |
v-model:custom | Çoklu model desteği |
v-model.trim | Giriş metnini kırpar |
v-model.lazy | Input yerine change event’ini dinler |
Sonuç
v-model, Vue’nun reaktivite mimarisinde zarif bir veri alışveriş protokolüdür. Bir props ve bir emit çiftinden ibaret gibi görünse de, componentler arası iletişimi kolaylaştıran güçlü bir standarttır.Kısaca:
modelValue→ veri içeriupdate:modelValue→ veri dışarıv-model→ ikisini otomatik bağlar
Bu mantığı anladığında, artık her bileşeni “form element” gibi çalıştırabilir, karmaşık veri akışlarını zahmetsizce yönetebilirsin.