Vue ile bileşen tabanlı arayüz mimarisine geçiş
Sayfa odaklı düşünmekten bileşen (component) odaklı düşünmeye geçişi ve Vue.js'in bunu pratikte nasıl sağladığını anlatıyorum.
Uzun süre arayüz geliştirirken kafamda “sayfa” kavramı vardı. Bir sayfa var, içinde bir form var, form gönderilince bir şey oluyor. jQuery ile event listener’lar yazıyordum, DOM’u elle güncelliyordum, her şey bir aradaydı. Küçük projelerde bu yeterdi. Ama sayfa büyüdükçe, farklı yerlerde aynı UI parçası tekrarlandıkça, “bu kodu nereye koyacağım” sorusu cevapsız kalmaya başladı.
Vue.js ile çalışmaya başladıktan sonra o soruyu sormayı bıraktım. Çünkü artık “sayfayı” değil, “bileşeni (component)” birim olarak düşünüyorum.
Bileşen nedir?
Bileşen, kendi şablonunu, mantığını ve stilini bir arada barındıran, yeniden kullanılabilir bir arayüz birimidir. Bir düğme, bir form alanı, bir kart, bir açılır menü — bunların her biri ayrı bir bileşen olabilir.
Vue’da tek dosyalı bileşen (Single File Component — SFC) formatı bu ayrımı çok somutlaştırıyor. .vue uzantılı bir dosya açtığınızda şablonu, JavaScript mantığını ve CSS’i aynı yerde görüyorsunuz:
<template>
<div class="user-card">
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
</div>
</template>
<script>
export default {
props: {
user: {
type: Object,
required: true
}
}
}
</script>
<style scoped>
.user-card {
padding: 1rem;
border: 1px solid #ddd;
}
</style>
Bu bileşeni istediğim her yerde şöyle kullanabiliyorum:
<UserCard :user="currentUser" />
Sayfa değil, bileşen hiyerarşisi
Bileşen odaklı düşünmenin en büyük değişikliği şu oldu: artık bir sayfayı tasarlamak yerine o sayfayı oluşturacak bileşenlerin hiyerarşisini tasarlıyorum.
Örneğin bir kullanıcı listesi sayfası düşünelim. Eskiden tek bir HTML dosyasında her şeyi yazardım. Şimdi:
UserListPage— sayfa bileşeni, veriyi çekerUserList— listeyi render eden bileşenUserCard— tek bir kullanıcıyı gösteren kart
Bu üçü ayrı ayrı dosyalar. UserCard’ı başka bir sayfada da kullanabiliyorum; değiştirmem gerektiğinde tek bir yerde değiştiriyorum.
Veri akışı: props ve event
Bileşenler arası iletişim başlangıçta kafamı karıştırdı. Vue’nun yaklaşımı şu: veri yukarıdan aşağıya akar (props aracılığıyla), olaylar aşağıdan yukarıya çıkar (emit aracılığıyla).
Üst bileşen, alt bileşene props ile veri geçirir. Alt bileşen bir şey değiştirmek istediğinde, bunu doğrudan değiştirmez; bir event yayar.
<!-- Alt bileşen: DeleteButton.vue -->
<template>
<button @click="handleClick">Sil</button>
</template>
<script>
export default {
methods: {
handleClick() {
this.$emit('delete')
}
}
}
</script>
<!-- Üst bileşen -->
<DeleteButton @delete="removeUser(user.id)" />
Bu kural ilk başta fazla resmi görünüyor. Ama birkaç iç içe bileşenle çalıştığınızda, verinin nerede değiştiğini net olarak görebilmek gerçekten büyük bir rahatlık.
Yeniden kullanılabilirlik pratikte ne kazandırıyor?
Geçen ay üzerinde çalıştığım projede aynı kart tasarımını dört farklı sayfada kullandım. Renk temasını değiştirmem gerektiğinde tek dosyayı güncelledi, dört sayfa anında değişti. Eskiden bu değişikliği dört ayrı dosyada, büyük ihtimalle birinde unutarak yapardım.
Yeniden kullanılabilirlik soyut bir kavram gibi durur; ama pratikte “dört yerde değil bir yerde değiştir” anlamına geliyor. Bu küçük fark, proje büyüdükçe çok daha önemli hâle geliyor.
Ne zaman bileşene bölmeli?
Her şeyi bileşene bölmek de doğru değil. Çok küçük ya da çok özel bir şeyi bileşene ayırmak gereksiz karmaşıklık yaratıyor. Benim şu an uyguladığım kural basit: bir arayüz parçası birden fazla yerde kullanılacaksa, ya da kendi içinde anlamlı bir mantığı varsa, bileşen olsun.
Tek seferlik ve sayfa özelinde bir şeyse, sayfa bileşeninin şablonu içinde kalmaya devam edebilir. Refactor etmek her zaman mümkün; erken soyutlamak yerine ihtiyaç ortaya çıkınca ayırmayı tercih ediyorum.
Geçiş süreci
Tamamen yeni bir proje başlatmak farklı; ama mevcut bir projeye Vue eklemek de kademeli yapılabiliyor. Vue’yu tüm sayfaya değil, yalnızca dinamik olmasını istediğiniz bir DOM düğümüne mount edebiliyorsunuz. Bu sayede mevcut Blade şablonlarını korurken yalnızca ihtiyaç duyduğunuz yerleri bileşenlere dönüştürebiliyorum.
Bileşen odaklı düşünmek bir süre alıyor. Ama bir kez içselleştirdiğinizde, sayfayı monolitik bir blok olarak değil, birleştirilebilir parçaların toplamı olarak görmek çok daha doğal hissettiriyor.