Nuxt3: Componentler arası iletişim

Ahmet Hüzeyfe Demir
inventiv
Published in
5 min readOct 31, 2023

Component Nedir?

Componentler uygulamaların önemli bir parçasıdır. Componentler kullanılarak kullanıcı arayüzü daha küçük parçalara bölünebilir. Bu sayede uygulamanızı daha modüler, organize ve tekrar kullanılabilir hale getirmenize yardımcı olur.

Componentler iç içe kullanılabilir ve bir ağaç yapısı oluşturur.

Nuxt3 de component oluşturmak için components/ dizinine .vue uzantılı bir dosya oluşturmanız yeterlidir. Oluşturulan bu component uygulamanın herhangi bir yerinde kullanılabilir.

Proje dosya yapısı

Componentler arası ilişkiler

Nuxt3 te componentlar arasındaki ilişkiler, Vue’nin mevcut Composition API’si kullanılarak tanımlanır. Composition API, componentlerin verilerini ve davranışlarını daha esnek ve tekrar kullanılabilir bir şekilde yönetmenin bir yolunu sunar.

Componentler arası ilişkiler ve veri alışverişi için kullanılan yöntemlerden bazıları aşağıda verilmiştir.

Parent-child ilişkileri kullanılarak, bileşenler arasında veri paylaşımı ve veri akışı kolaylaştırılabilir. Bu, uygulamanızın daha temiz ve daha kolay anlaşılır olmasını sağlar.

1) Props

Props ile Parent dan Child componente doğru veri aktarımı sağlanabilir. Props lar key:value şeklinde tanımlanır. Bu veriler Child componentin davranışını kontrol etmek, görünüşünü değiştirmek veya veri aktarımı için kullanılabilir.

Aşağıdaki örnekte child componente props kullanılarak componentTitle değeri gönderilmiştir.

<!-- app.vue -->
<template>
<div class="parent">
<h1>Parent Component</h1>


<br /><br /><br /><br />
<div>
<ChildComponent componentTitle="Child Component" />
</div>
</div>
</template>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<h2>{{ props.componentTitle }}</h2>
</div>
</template>
<script setup>
const props = defineProps(["componentTitle"]);
</script>
Props

2) Provide/Inject

Componentler arası veri paylaşımını sağlayan bir mekanizmadır. Provide, bir componentin verilerini başka componentlere sunmak için kullanılır. Inject ise herhangi bir componentten provide edilen veriyi başka bir componentten okumak için kullanılır.

Parent componentin Child componentine veri aktarırken Props kullanılabilir. İki component arasında doğrudan bir ilişki yok ise Provide/Inject kullanmak gerekir.

Aşağıdaki resimde gösterildiği gibi Root dan Footer’a doğrudan ilişki olduğundan Props ile veri geçilebilir. Ancak DeepChild componenti ile doğrudan bir bağı olmadığından Provide/Inject ile veri gönderilebilir.

Provide/Inject kullanmak için öncelikle provide etmek istediğiniz verileri tanımlamanız gerekir. Bunu, provide() metoduyla yapabilirsiniz. provide() metodu iki parametre alır: provide edilecek veriyi tanımlayan isim ve verinin içeriği. inject() metodu ise provide edilen veriyi döndürür ve parametre olarak veriyi tanımlayan ismi alır.

<!-- app.vue -->
<template>
<div class="parent">
<h1>Parent Component</h1>
<button @click="greetingMessageStatus = !greetingMessageStatus">
Change Greeting Message
</button>

<br /><br /><br /><br />
<div>
<ChildComponent componentTitle="Child Component" />
</div>
</div>
</template>
<script setup>
const greetingMessageStatus = ref(true);
provide("greetingMessageStatus", greetingMessageStatus);
</script>
<style scoped>
.parent {
margin: 50px;
padding: 50px;
padding-bottom: 50px;
background-color: blanchedalmond;
}
</style>
<!-- DeepChildComponent.vue -->
<template>
<div class="deepChild">
<h3>Deep Child Component</h3>
<h4 style="color: white;">{{ greetingMessage }}</h4>
</div>
</template>
<script setup>
const greetingMessageStatus = inject("greetingMessageStatus");
let greetingMessage = ref("Welcome!");
watch(greetingMessageStatus, (newValue) => {
greetingMessage.value = newValue == true ? "Welcome!" : "Goodbye!";
});
</script>
<style scoped>
.deepChild {
background-color: burlywood;
padding: 10px;
padding-bottom: 50px;
margin-top: 70px;
}
</style>
Provide/Inject

Yukarıda görüldüğü gibi DeepChild da bulunan mesaj verisi Parent dan değiştirilebiliyor.

3) Refs

Refs, bir componentin child componentine doğrudan erişim sağlayan bir mekanizmadır.

Parent component içinde çağırılan child componente bir ref verilir ve bunun üzerinden child componentin sağladığı veri ve metodlara erişilebilir.

Child component içinde defineExpose() metodu içine parentden ulaşılmak istenen metod ve değişkenler eklenir.

<!-- app.vue -->
<template>
<div class="parent">
<h1>Parent Component</h1>
<!-- Provide/Inject -->
<button @click="greetingMessageStatus = !greetingMessageStatus">
Change Greeting Message
</button>
Provide/Inject
<hr />
<!-- Refs -->
<button style="color: red" @click="callChildComponentMethod">
Call Child Component Method
</button>
Refs

<br /><br /><br /><br />
<div>
<ChildComponent componentTitle="Child Component" ref="childComponent" />
</div>
</div>
</template>
<script setup>
//Provide/Inject
const greetingMessageStatus = ref(true);
provide("greetingMessageStatus", greetingMessageStatus);
//Refs
const childComponent = ref(null);
function callChildComponentMethod() {
childComponent.value.raiseAlert();//Child componentin metoduna erisiliyor.
}
</script>
<style scoped>
.parent {
margin: 50px;
padding: 50px;
padding-bottom: 50px;
background-color: blanchedalmond;
width: 700px;
}
</style>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<h2>{{ props.componentTitle }}</h2>

<!-- Provide/Inject -->
<DeepChildComponent />

<!-- Refs -->
<div v-show="isVisible" class="alert">This is ChildComponent!</div>
</div>
</template>
<script setup>
//Props
const props = defineProps(["componentTitle"]);

//Refs
const isVisible = ref(false);
function raiseAlert() {
isVisible.value = !isVisible.value;
}
defineExpose({
raiseAlert,
});
</script>
<style scoped>
.child {
background-color: azure;
padding: 10px;
padding-bottom: 50px;
width: 500px;
}
.alert {
padding: 20px;
background-color: #f44336; /* Red */
color: white;
margin-bottom: 15px;
}
</style>
Refs

Parent component den child componentte ki metod tetiklenerek childın içinde bulunan alert gösteriliyor.

4) Emit & Event

Bu yöntemde child component den emit edilen bir eventin parent tarafından yakalanıp parent component de olan bir metodun tetiklenmesi sağlanılabilir.

<!-- app.vue -->
<template>
<div class="parent">
<h1>Parent Component</h1>
<!-- Provide/Inject -->
<button @click="greetingMessageStatus = !greetingMessageStatus">
Change Greeting Message
</button>
Provide/Inject
<hr />
<!-- Refs -->
<button style="color: red" @click="callChildComponentMethod">
Call Child Component Method
</button>
Refs

<!-- Emit & Event -->
<hr />
<div v-show="isVisible" class="alert">This is ParentComponent!</div>

<br /><br />
<div>
<ChildComponent
componentTitle="Child Component"
ref="childComponent"
@raise-parent-alert="raiseAlert"
/>
</div>
</div>
</template>
<script setup>
//Provide/Inject
const greetingMessageStatus = ref(true);
provide("greetingMessageStatus", greetingMessageStatus);

//Refs
const childComponent = ref(null);
function callChildComponentMethod() {
childComponent.value.raiseAlert();
}

//Emit & Event
const isVisible = ref(false);
function raiseAlert() {
isVisible.value = !isVisible.value;
}
</script>
<style scoped>
.parent {
margin: 50px;
padding: 50px;
padding-bottom: 50px;
background-color: blanchedalmond;
width: 700px;
}
.alert {
padding: 20px;
background-color: plum;
color: white;
margin-bottom: 15px;
}
</style>
<!-- ChildComponent.vue -->
<template>
<div class="child">
<h2>{{ props.componentTitle }}</h2>

<!-- Provide/Inject -->
<DeepChildComponent />

<!-- Refs -->
<div v-show="isVisible" class="alert">This is ChildComponent!</div>

<!-- Emit & Event -->
<hr />
<button style="color: red" @click="callParentComponentMethod">
Call Parent Component Method
</button>
Emit & Event
</div>
</template>
<script setup>
//Props
const props = defineProps(["componentTitle"]);

//Refs
const isVisible = ref(false);
function raiseAlert() {
isVisible.value = !isVisible.value;
}
defineExpose({
raiseAlert,
});

//Emit & Event
const emit = defineEmits(["raiseParentAlert"]);
function callParentComponentMethod() {
emit("raiseParentAlert");
}
</script>
<style scoped>
.child {
background-color: azure;
padding: 10px;
padding-bottom: 50px;
width: 500px;
}
.alert {
padding: 20px;
background-color: #f44336; /* Red */
color: white;
margin-bottom: 15px;
}
</style>
Emit & Event

Yukarıda görüldüğü üzere child componentte bulunan bir butondan event emit edilerek parent componentte yakalanıp alert gösterilmesi sağlanmıştır.

Makalemizin sonucunda Nuxt3 kullanılarak bir uygulamada componentler arası iletişimi nasıl sağlayacağımızı görmüş olduk. Umarım faydalı bir yazı olmuştur.

Katkılarından dolayı Kaan Başöz ve Enes BABAOĞLU’na teşekkür ederim.

Kaynak kodlara buradan ulaşabilirsiniz: https://github.com/koyuboy/Nuxt3ComponentsCommunication

Kaynakça

--

--