Vue.js Composition API: Kapsamlı Rehber

Vue 3 ile gelen Composition API özelliklerini detaylı olarak inceleyelim ve nasıl kullanacağımızı öğrenelim

12 dk okuma
Vue.jsComposition APIJavaScriptFrontend

Vue.js Composition API: Kapsamlı Rehber

Vue 3 ile birlikte gelen Composition API, Vue.js'de component logic'i organize etmenin yeni ve güçlü bir yolunu sunuyor. Bu yazıda Composition API'nin temellerinden ileri seviye kullanımına kadar her şeyi ele alacağız.

Composition API Nedir?

Composition API, Vue bileşenlerinde mantığı organize etmek için function-based bir yaklaşım sunar. Options API'ye alternatif olarak geliştirilmiş ve özellikle büyük projelerde kod tekrarını azaltır ve mantığı daha iyi organize etmeyi sağlar.

Temel Avantajları

  • Daha İyi Logic Reuse: Mantığı farklı bileşenler arasında kolayca paylaşabilirsiniz
  • TypeScript Desteği: Daha iyi tip güvenliği
  • Daha Esnek Organizasyon: İlgili mantığı bir arada tutabilirsiniz
  • Tree-shaking: Kullanılmayan kodları otomatik olarak temizler

Temel Kullanım

setup() Fonksiyonu

Composition API'nin kalbi setup() fonksiyonudur:

<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Artır</button>
  </div>
</template>

<script>
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    
    const increment = () => {
      count.value++
    }
    
    return {
      count,
      increment
    }
  }
}
</script>

Script Setup Syntax

Daha kısa syntax için <script setup> kullanabilirsiniz:

<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Artır</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const count = ref(0)

const increment = () => {
  count.value++
}
</script>

Reactivity Fundamentals

ref() vs reactive()

ref() - Primitive değerler için:

import { ref } from 'vue'

const count = ref(0)
const message = ref('Merhaba')

// Değere erişim
console.log(count.value) // 0
count.value = 1

reactive() - Objeler için:

import { reactive } from 'vue'

const state = reactive({
  count: 0,
  message: 'Merhaba'
})

// Doğrudan erişim
console.log(state.count) // 0
state.count = 1

computed() ve watch()

Computed Properties:

import { ref, computed } from 'vue'

const firstName = ref('Eralp')
const lastName = ref('Özcan')

const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`
})

Watchers:

import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newValue, oldValue) => {
  console.log(`Count changed from ${oldValue} to ${newValue}`)
})

// Immediate watch
watch(count, (newValue) => {
  console.log('Count:', newValue)
}, { immediate: true })

Lifecycle Hooks

Composition API'de lifecycle hook'ları on prefix'i ile kullanılır:

import { onMounted, onUpdated, onUnmounted } from 'vue'

export default {
  setup() {
    onMounted(() => {
      console.log('Component mounted')
    })
    
    onUpdated(() => {
      console.log('Component updated')
    })
    
    onUnmounted(() => {
      console.log('Component unmounted')
    })
  }
}

Composables - Logic Reuse

Composables, mantığı farklı bileşenler arasında paylaşmanın harika bir yoludur:

// composables/useCounter.js
import { ref } from 'vue'

export function useCounter(initialValue = 0) {
  const count = ref(initialValue)
  
  const increment = () => count.value++
  const decrement = () => count.value--
  const reset = () => count.value = initialValue
  
  return {
    count,
    increment,
    decrement,
    reset
  }
}

Kullanımı:

<script setup>
import { useCounter } from '@/composables/useCounter'

const { count, increment, decrement, reset } = useCounter(10)
</script>

Gerçek Dünya Örneği: Todo App

<template>
  <div class="todo-app">
    <input 
      v-model="newTodo" 
      @keyup.enter="addTodo"
      placeholder="Yeni todo ekle..."
    >
    
    <ul>
      <li 
        v-for="todo in filteredTodos" 
        :key="todo.id"
        :class="{ completed: todo.completed }"
      >
        <input 
          type="checkbox" 
          v-model="todo.completed"
        >
        <span>{{ todo.text }}</span>
        <button @click="removeTodo(todo.id)">Sil</button>
      </li>
    </ul>
    
    <div class="filters">
      <button 
        v-for="filter in filters" 
        :key="filter"
        @click="currentFilter = filter"
        :class="{ active: currentFilter === filter }"
      >
        {{ filter }}
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'

const newTodo = ref('')
const todos = ref([])
const currentFilter = ref('All')
const filters = ['All', 'Active', 'Completed']

const addTodo = () => {
  if (newTodo.value.trim()) {
    todos.value.push({
      id: Date.now(),
      text: newTodo.value,
      completed: false
    })
    newTodo.value = ''
  }
}

const removeTodo = (id) => {
  todos.value = todos.value.filter(todo => todo.id !== id)
}

const filteredTodos = computed(() => {
  switch (currentFilter.value) {
    case 'Active':
      return todos.value.filter(todo => !todo.completed)
    case 'Completed':
      return todos.value.filter(todo => todo.completed)
    default:
      return todos.value
  }
})
</script>

Best Practices

  1. Mantığı Gruplandırın: İlgili state ve fonksiyonları bir arada tutun
  2. Composables Kullanın: Tekrar eden mantığı composable'lara çıkarın
  3. TypeScript Kullanın: Daha iyi developer experience için
  4. Destructuring: Return edilen değerleri destructure edin
  5. Naming Convention: Composable'lar için use prefix'i kullanın

Sonuç

Composition API, Vue.js'de component logic'i organize etmenin güçlü ve esnek bir yolunu sunar. Özellikle büyük projelerde kod tekrarını azaltır ve maintainability'yi artırır.

Faydalı Kaynaklar


Bu yazıda Composition API'nin temellerini ve pratik kullanımını ele aldık. Sorularınız için benimle iletişime geçebilirsiniz.