Ana içeriğe geç

Bileşen Temelleri

Bileşenler Temelleri

Bileşenler, UI'yi bağımsız ve yeniden kullanılabilir parçalara ayırmamıza ve her parçayı izolasyonda düşünmemize olanak tanır. Bir uygulamanın genellikle iç içe geçmiş bileşenlerden oluşan bir ağaç yapısına organize edilmesi yaygındır:

Bu, yerel HTML öğelerini nasıl iç içe aldığımıza oldukça benzer, ancak Vue, her bileşende özel içerik ve mantığı kapsüllememizi sağlayan kendi bileşen modelini uygular. Vue, yerel Web Bileşenleri ile de uyumlu çalışır. Vue Bileşenleri ve yerel Web Bileşenleri arasındaki ilişki hakkında daha fazla bilgi edinmek istiyorsanız, buradan daha fazla bilgi okuyun.

Bir Bileşeni Tanımlama

Bir derleme adımı kullanırken, tipik olarak her Vue bileşenini .vue uzantılı özel bir dosyada tanımlarız - buna Tek Dosya Bileşeni (kısa SFC) denir:

<script>
export default {
data() {
return {
count: 0
}
}
}
</script>

<template>
<button @click="count++">Bana {{ count }} kez tıkladınız.</button>
</template>
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
<button @click="count++">Bana {{ count }} kez tıkladınız.</button>
</template>

Bir derleme adımı kullanmıyorsanız, bir Vue bileşeni, Vue'ya özel seçenekleri içeren düz bir JavaScript nesnesi olarak tanımlanabilir:

export default {
data() {
return {
count: 0
}
},
template: `
<button @click="count++">
Bana {{ count }} kez tıkladınız.
</button>`
}
import { ref } from 'vue'

export default {
setup() {
const count = ref(0)
return { count }
},
template: `
<button @click="count++">
Bana {{ count }} kez tıkladınız.
</button>`
// Ayrıca bir DOM içindeki şablonu hedefleyebilirsiniz:
// template: '#my-template-element'
}

Şablon burada bir JavaScript dizesi olarak satır içi olarak tanımlanmıştır, bu da Vue'nun bunu anlık olarak derleyeceği anlamına gelir. Ayrıca, bir öğeye (genellikle yerel `` öğeleri) işaret eden bir ID seçicisi de kullanabilirsiniz - Vue, içeriğini şablon kaynağı olarak kullanacaktır.

Yukarıdaki örnek, bir bileşen tanımlar ve onu bir .js dosyasının varsayılan ihracı olarak dışarı aktarır, ancak aynı dosyadan birden fazla bileşen dışa aktarmak için adlandırılmış dışa aktarımlar da kullanabilirsiniz.

Bir Bileşeni Kullanma

ipucu

Bu kılavuzun geri kalanında SFC sözdizimini kullanacağız - bileşenler etrafındaki kavramlar, bir derleme adımı kullanıp kullanmadığınızdan bağımsız olarak aynıdır. Örnekler bölümü, her iki senaryoda da bileşen kullanımını gösterir.

Bir alt bileşeni kullanmak için, onu üst bileşende içe aktarmamız gerekir. Sayma bileşenimizi ButtonCounter.vue adlı bir dosyanın içine yerleştirdiğimizi varsayalım, bileşen dosyanın varsayılan ihracı olarak kullanılabilir hale gelecektir:

<script>
import ButtonCounter from './ButtonCounter.vue'

export default {
components: {
ButtonCounter
}
}
</script>

<template>
<h1>İşte bir alt bileşen!</h1>
<ButtonCounter />
</template>
<script setup>
import ButtonCounter from './ButtonCounter.vue'
</script>

<template>
<h1>İşte bir alt bileşen!</h1>
<ButtonCounter />
</template>

`` ile, içe aktarılan bileşenler otomatik olarak şablona sunulmaktadır.

Ayrıca, bir bileşeni küresel olarak kaydetmek mümkündür, böylece bir uygulamadaki tüm bileşenler için onu içe aktarmaya gerek kalmadan kullanılabilir. Küresel ve yerel kayıt arasındaki avantajlar ve dezavantajlar, özel Bileşen Kaydı bölümünde tartışılmıştır.

Bileşenleri istediğiniz kadar tekrar kullanabilirsiniz:

<h1>İşte birçok alt bileşen!</h1>
<ButtonCounter />
<ButtonCounter />
<ButtonCounter />

Playground'da deneyin

Playground'da deneyin

Düğmelere tıkladığınızda, her birinin kendi, ayrık count'ını koruduğunu unutmayın. Bunun nedeni, bir bileşeni kullandığınızda, onun yeni bir örneği oluşturulmasıdır.

SFC'lerde, alt bileşenlerin etiket adları için PascalCase kullanmanız önerilir, bu sayede yerel HTML öğelerinden ayırt edebilirsiniz. Yerel HTML etiket adları büyük/küçük harfe duyarsız olsa da, Vue SFC derlenmiş bir format olduğundan, içindeki büyük/küçük harfe duyarlı etiket adlarını kullanabiliyoruz. Ayrıca, bir etiketi kapatmak için /> kullanabiliyoruz.

Eğer şablonlarınızı doğrudan bir DOM'da yazıyorsanız (örneğin, yerel bir `öğesinin içeriği olarak), şablon, tarayıcının yerel HTML analiz davranışına tabi olacaktır. Bu tür durumlarda,kebab-case` ve bileşenler için açık kapanış etiketleri kullanmanız gerekecektir:

<!-- eğer bu şablon DOM'da yazılmışsa -->
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>

Daha fazla bilgi için DOM içi şablon analizi tuzaklarına bakın.

Props Geçişi

Eğer bir blog oluşturuyorsak, muhtemelen bir blog gönderisini temsil eden bir bileşene ihtiyacımız olacaktır. Tüm blog gönderilerinin aynı görsel düzeni paylaşmasını istiyoruz, ancak farklı içerikle. Böyle bir bileşen faydalı olmayacaktır, eğer ona belirli bir gönderiyi göstermek için başlık ve içerik gibi veriler geçemezsek. İşte burada props devreye giriyor.

Props, bir bileşen üzerinde kayıt yapabileceğiniz özel niteliklerdir. Blog gönderi bileşenimize bir başlık geçmek için, bu bileşenin kabul ettiği props listesinde başlığı belirtmemiz gerekir; bunu props seçeneğinidefineProps makrosunu kullanarak yaparız:

<!-- BlogPost.vue -->
<script>
export default {
props: ['title']
}
</script>

<template>
<h4>{{ title }}</h4>
</template>
<!-- BlogPost.vue -->
<script setup>
defineProps(['title'])
</script>

<template>
<h4>{{ title }}</h4>
</template>

defineProps, yalnızca `içinde mevcut olan ve açıkça içe aktarılmasına gerek olmayan bir derleme zamanı makrosudur. Tanımlanan props, otomatik olarak şablona sunulmaktadır.defineProps` ayrıca, bileşene geçirilen tüm props'u içeren bir nesne döner; böylece ihtiyaç halinde JavaScript'te onlara erişebiliriz:

const props = defineProps(['title'])
console.log(props.title)

Ayrıca: Bileşen Props'larının Tipi

Eğer `kullanmıyorsanız, props,propsseçeneği kullanılarak tanımlanmalıdır ve props nesnesi,setup()`'a ilk argüman olarak geçilecektir:

export default {
props: ['title'],
setup(props) {
console.log(props.title)
}
}

Bir bileşen, istediğiniz kadar prop'a sahip olabilir ve varsayılan olarak, herhangi bir değer herhangi bir prop'a geçirilebilir.

Bir prop kaydedildikten sonra, ona özel bir nitelik olarak veri geçebilirsiniz, şöyle:

<BlogPost title="Vue ile yolculuğum" />
<BlogPost title="Vue ile blog yazmak" />
<BlogPost title="Neden Vue bu kadar eğlenceli" />

Ancak tipik bir uygulamada, muhtemelen üst bileşeninizde bir dizi gönderi olacaksınız:

export default {
// ...
data() {
return {
posts: [
{ id: 1, title: 'Vue ile yolculuğum' },
{ id: 2, title: 'Vue ile blog yazmak' },
{ id: 3, title: 'Neden Vue bu kadar eğlenceli' }
]
}
}
}
const posts = ref([
{ id: 1, title: 'Vue ile yolculuğum' },
{ id: 2, title: 'Vue ile blog yazmak' },
{ id: 3, title: 'Neden Vue bu kadar eğlenceli' }
])

Daha sonra, her biri için bir bileşeni, v-for kullanarak render etmek isteriz:

<BlogPost
v-for="post in posts"
:key="post.id"
:title="post.title"
/>

Playground'da deneyin

Playground'da deneyin

v-bind sözdizimi (:title="post.title"`) kullanılarak dinamik prop değerleri geçirildiğine dikkat edin. Bu, önceden hangi içeriği render edeceğinizi kesin olarak bilmediğinizde özellikle faydalıdır.

Şu anda props hakkında bilmeniz gereken her şey bu, ancak bu sayfayı okuduktan sonra içeriği ile rahat hissettiğinizde, Props hakkında tam kılavuzu daha sonra okumayı öneririz.

Olayları Dinleme

`` bileşenimizi geliştirirken, bazı özellikler üst bileşene geri bildirimde bulunmayı gerektirebilir. Örneğin, blog gönderilerinin metnini büyütmek için erişilebilirlik özelliği eklemeye karar verebiliriz; bu esnada sayfanın geri kalanını varsayılan boyutunda bırakabiliriz.

Üst bileşende, bu özelliği desteklemek için bir postFontSize veri niteliğiref ekleyebiliriz:

data() {
return {
posts: [
/* ... */
],
postFontSize: 1
}
}
const posts = ref([
/* ... */
])

const postFontSize = ref(1)

Bu, tüm blog gönderilerinin font büyüklüğünü kontrol etmek için şablon içinde kullanılabilir:

<div :style="{ fontSize: postFontSize + 'em' }">
<BlogPost
v-for="post in posts"
:key="post.id"
:title="post.title"
/>
</div>

Artık `` bileşeninin şablonuna bir buton ekleyelim:

<!-- BlogPost.vue, <script> kısmını atlayarak -->
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button>Metni Büyüt</button>
</div>
</template>

Buton henüz hiçbir şey yapmıyor - butona tıkladığınızda, üst bileşene blog gönderilerinin hepsinin metnini büyütmesi gerektiği bilgisini iletmek istiyoruz. Bu problemi çözmek için, bileşenler özel bir olay sistemi sağlar. Üst bileşen, v-on veya @ ile herhangi bir alt bileşen örneğinde herhangi bir olayı dinlemeyi seçebilir; bu, yerel DOM olayıyla aynı şekilde çalışır:

<BlogPost
...
@enlarge-text="postFontSize += 0.1"
/>

Sonra, alt bileşen, kendisinde bir olay yaymak için yerleşik **$emit** metodunu çağırabilir ve olayın adını geçebilir:

<!-- BlogPost.vue, <script> kısmını atlayarak -->
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">Metni Büyüt</button>
</div>
</template>

@enlarge-text="postFontSize += 0.1" dinleyicisi sayesinde, üst bileşen olayı alacak ve postFontSize değerini güncelleyecektir.

Playground'da deneyin

Playground'da deneyin

Olayları belirtebiliriz

Angular'ın bileşenleri, kullandığımız @emit özelliğini kullanarak özel olayları destekleyebilir. İşte aşağıdaki kodda dolu bir örnek.

İçerik Dağıtımı ile Slotlar

Tıpkı HTML öğeleri gibi, bir bileşene içerik geçirebilmek sık sık faydalıdır, şuna benzeyen bir şekilde:

<AlertBox>
Kötü bir şey oldu.
</AlertBox>

Bu, muhtemelen şöyle bir şeye render edilebilir:

Bu Demo Amaçlı bir Hata

Kötü bir şey oldu.

Bu, Vue'nun özel `` öğesini kullanarak gerçekleştirilebilir:

<!-- AlertBox.vue -->
<template>
<div class="alert-box">
<strong>Bu Demo Amaçlı bir Hata</strong>
<slot />
</div>
</template>

<style scoped>
.alert-box {
/* ... */
}
</style>

Gördüğünüz gibi, içeriğin nereye gitmesini istediğimiz yere `` kullanıyoruz - hepsi bu kadar. İşimiz bitti!

Playground'da deneyin

Playground'da deneyin

Şu anda slotlar hakkında bilmeniz gereken her şey bu, ancak bu sayfayı okuduktan sonra içeriği ile rahat hissettiğinizde, Slotlar hakkında tam kılavuzu daha sonra okumayı öneririz.