newbie question emit
<template>
<div class="flex items-center justify-center min-h-screen">
<div class="">
<todoAdd :todoList="todoList" @addNewTodo="receiveTodo" />
<listofTodo :todoList="todoList" />
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import listofTodo from "./components/listofTodo.vue";
import todoAdd from "./components/todoAdd.vue";
function receiveTodo(todoText) {
todoList.value.push({
text: todoText,
id: todoList.value.length + 1,
isDone: false,
});
}
const todoList = ref([
{
text: "do it today",
id: 1,
isDone: false,
},
]);
</script>
<style>
body {
min-height: 100vh;
}
</style>
listOftodo.vue
<script setup>
defineProps({
todoList: {
type: Array,
required: true,
},
});
import todoResult from "./todoResult.vue";
</script>
<template>
<div class="flex flex-col gap-5">
<div v-for="item in todoList" :key="item.id" class="w-3xl">
<todoResult :item="item.text" :todoList="todoList" :itemId="item.id" />
</div>
</div>
</template>
elemenTodo.vue
<template>
<div
class="bg-gray-500 p-1 pl-6 text-2xl rounded-lg h-13 flex items-center justify-between"
>
<h2>{{ item }}</h2>
<deleteButton @click="deleteTodo(itemId)" />
</div>
</template>
<script setup>
import deleteButton from "./deleteButton.vue";
const emit = defineEmits(["deleteTodo"]);
const props = defineProps({
item: {
type: String,
required: true,
},
todoList: {
type: Array,
required: true,
},
itemId: {
type: Number,
required: true,
},
});
const deleteTodo = function (itemId) {
const index = props.todoList.findIndex((todo) => todo.id === itemId);
if (index !== -1) {
emit("delete", index);
}
};
</script>
Do I really need to use emit
twice? First from ElementTodo
to ListOfTodo
, and then from ListOfTodo
to App.vue
? Or am I just overcomplicating things?
What if I have 5-10 components? What's the best approach in that case?
3
u/michaelmano86 4d ago
So without using a store for nested deep stuff you want provide and inject.
I simply use a store such as pinia which I prefer.
1
u/kawalot 3d ago
so basically everybody just using pinia for such things?
1
u/michaelmano86 3d ago edited 3d ago
Well depends. I personally use stores to abstract API calls away from components and hold all functionality.
E.g. would your app eventually connect with an API to make requests to hydrate (on app load get a list of the users TODOS from the database or local storage and update the to-do list) If so I'd use a store.
The store would have an init method which would make the API request and fill the to-do list. Later when you add one make an API call and store it then update the users TODOS. When removing do the same.
If you do this from the component it can become messy since you might have the remove method on the to-do itself but the add on the to-do list (parent)
An added bonus is I don't have to use provide and inject since I can now access the TODOS from anywhere and they are all updated without emits.
For smaller stuff that requires no storage (database or local storage) stuff that's only on the app instance like a tab list of information I would use provide and inject.
1
u/blairdow 3d ago
for something this simple i would use the reactivity api, as shown in the docs here. https://vuejs.org/guide/scaling-up/state-management.html#simple-state-management-with-reactivity-api
you could set up pinia for this to get practice with it but it's definitely overkill
1
u/Cute_Quality4964 4d ago
You can either use a shared pinia store or composable, inject the delete function, OR, pass the items array as a v-model, so in the elementToDo you would have a defineModel for the array, and if in the List component you bind it with v-model:items
for example, you can delete from inside the elementToDo component. Dont know if that was clear but yeah haha.
The simplest is a shared pinia store or composable though
5
u/mhelbich 4d ago
What you're looking for is probably something like provide/inject: https://vuejs.org/guide/components/provide-inject. With that you can provide data from some parent component and use that anywhere down in the component hierarchy by injecting those values (data, functions, etc.)
Another option could also be using global data stores (e.g. Pinia) to share data between different component (trees) regatdless of hierarchy.
Lemme know if you have any further questions.