Vue Composition API, Vue 3 ile gelen ve bileşen mantığını data, methods, computed gibi seçeneklere dağıtmak yerine tek bir setup fonksiyonunda toplamaya yarayan modern bir yazım biçimidir. Bu yazıda ref, reactive, computed ve watch gibi temel araçları gerçek örneklerle ele alıyorum; amaç, büyüdükçe okunması zorlaşan bileşenleri daha derli toplu ve yeniden kullanılabilir hâle getirmek.
Options API'den Composition API'ye
Klasik Options API'de bir bileşenin durumu (state), hesaplanan değerleri ve metotları ayrı bloklara dağılır. Küçük bileşenlerde bu sorun değildir, ancak bir özellik büyüdükçe aynı işe ait kod parçaları dosyanın dört bir yanına serpilir. Composition API ise ilgili mantığı bir arada tutmanı sağlar: bir sayaç mantığının state'i, hesaplaması ve fonksiyonu yan yana durur.
İki yaklaşım da Vue 3'te tam olarak desteklenir; Composition API zorunlu değil, bir seçenektir. Ama özellikle paylaşılabilir mantık (composable) yazarken belirgin avantaj sağlar.
setup ve <script setup>
Composition API'yi kullanmanın en pratik yolu <script setup> derleme zamanı (compile-time) sözdizimidir. Burada tanımladığın her değişken ve fonksiyon otomatik olarak template'e açılır; ayrıca return yazmana gerek kalmaz.
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">Sayı: {{ count }}</button>
</template>
Dikkat: JavaScript içinde değere count.value ile erişirsin, ama template içinde Vue .value'yu otomatik açar; orada sadece count yazarsın.
ref ile reaktif değerler
Tekil değerler (sayı, metin, boolean) için ref kullanılır. ref sana bir nesne döndürür ve gerçek değer onun .value özelliğinde tutulur. Bu, Vue'nun değer değiştiğinde DOM'u güncellemesini sağlayan reaktivite mekanizmasının temelidir.
- Okuma/yazma:
const name = ref('Ada')→name.value = 'Grace' - İlkel tipler için ideal: string, number, boolean.
- Nesne de tutabilir:
refiçine nesne koyarsan Vue içinireactiveile derin reaktif yapar.
reactive ile nesne durumu
Birden çok ilişkili alanı bir arada yönetmek istersen reactive uygundur. Bir nesneyi alır ve onu derin reaktif bir proxy'ye çevirir; burada .value yazmazsın, doğrudan özelliklere erişirsin.
import { reactive } from 'vue'
const form = reactive({
email: '',
agreed: false,
})
function submit() {
console.log(form.email, form.agreed)
}
Ne zaman hangisi? Pratik bir kural: ilkel değerler ve tek tek state parçaları için ref, mantıksal olarak bir bütün oluşturan form/nesne için reactive. reactive nesnesini bütünüyle yeniden atayamayacağını unutma (referans kopar); alanlarını güncelle ya da ref tercih et.
computed ile türetilmiş değerler
computed, başka reaktif değerlerden hesaplanan ve bağımlılıkları değişmedikçe önbelleğe alınan (cached) değerler üretir. Aynı sonucu template içinde tekrar tekrar hesaplamak yerine bir kez tanımlarsın.
import { ref, computed } from 'vue'
const price = ref(100)
const quantity = ref(3)
const total = computed(() => price.value * quantity.value)
total da bir ref gibi davranır: JavaScript'te total.value, template'te {{ total }}. price ya da quantity değiştiğinde Vue total'ı otomatik yeniden hesaplar.
watch ve watchEffect ile yan etkiler
Bir değer değiştiğinde ağ isteği atmak, localStorage'a yazmak gibi yan etkiler için watch kullanırsın. watch belirli bir kaynağı izler ve sana eski/yeni değeri verir.
import { ref, watch } from 'vue'
const query = ref('')
watch(query, (yeni, eski) => {
console.log(`'${eski}' -> '${yeni}'`)
})
watchEffect ise içinde kullandığın reaktif değerleri otomatik izler ve hemen bir kez çalışır; basit senaryolarda daha kısadır. Hangi bağımlılığı izlediğini açıkça görmek istediğinde watch, "kullanılan her şeyi izle" derken watchEffect daha uygun.
Composable: mantığı yeniden kullanma
Composition API'nin asıl gücü, mantığı bir fonksiyona çıkarıp birden çok bileşende paylaşabilmendir. Geleneksel olarak bu fonksiyonların adı use ile başlar.
// useCounter.js
import { ref } from 'vue'
export function useCounter(start = 0) {
const count = ref(start)
const increment = () => count.value++
const reset = () => (count.value = start)
return { count, increment, reset }
}
Artık herhangi bir bileşende const { count, increment } = useCounter(10) diyerek aynı mantığı tekrar kullanabilirsin. Mixin'lerin aksine burada hangi değerin nereden geldiği nettir ve isim çakışması yaşamazsın.
Sık Sorulan Sorular
ref mi reactive mi kullanmalıyım?
İlkel değerler ve tekil state için ref, mantıksal olarak bütün oluşturan nesneler/formlar için reactive. Çoğu ekip tutarlılık adına her şeyde ref kullanmayı tercih eder; ikisi de doğrudur.
Options API artık eski mi sayılıyor?
Hayır. Options API hâlâ tam desteklidir ve kaldırılmıyor. Composition API ek bir seçenek; özellikle büyük bileşenlerde ve paylaşılabilir mantıkta avantaj sağlar.
Template içinde neden .value yazmıyorum?
Vue, template'i derlerken üst seviyedeki ref'leri otomatik açar (unwrap eder). Bu yüzden template'te count, JavaScript içinde ise count.value yazarsın.
Vue projende Composition API'ye geçmek mi istiyorsun? Bileşen mimarinden composable tasarımına kadar birlikte temiz bir yapı kurabiliriz — benimle iletişime geç.