본문 바로가기

Vue/Vue3

[Vue2 vs Vue3] 기본내용정리2 (emit과 props)

1. 자식컴포넌트에서 부모컴포넌트로 이벤트를 전달할 수 있는 emit

 

Vue3  context.emit() / emits

emit은 자식에서 부모로 이벤트를 전달할때 매우 자주쓰이는데 vue2와 다른것은 Vue.$emit 이 아닌 context.emit()으로 전달한다는 것이다. 물론 context의 emit을 바로 사용하기 위에 { emit } 으로 받아와서 emit("이벤트이름", 전달할 데이터)로 사용해도 된다. 또 하나 다른점은 emits에 이벤트들을 정리해준다는 점이다.

1. setup의 인자값으로 context를 받는다.
2. context.emit("이벤트 이름", "전달할 데이터")를 여기에 넣는다.
3. emits에 정리해준다.

** 부모컴포넌트에서 받는 부분은 vue2와 동일

자식 컴포넌트 (context.emit으로 이벤트 전달)

<template>
   <form action="" @submit.prevent="addTodo">
        <input type="text" v-model="todo">
        <button type="submit">add</button>
    </form>
</template>

<script>
import { ref } from "vue";
export default {
	emits: ["add-todo"], //emit으로 보낼 이벤트 정리
    
    setup(props, context) {  //setup 2번째 매개변수에 context가 있음 이걸 {emit} 이렇게 받아도됨
        const todo = ref("");
        const hasError = ref(false);

        const addTodo = () => {
            if (todo.value === "") {
                hasError.value = true
            }
            else {
            // context 의 emit 이벤트로 이벤트 전달
            // 만약 위에서 {emit}으로 받앗다면 여기서 바로 emit("add-todo", {}) 로 사용가능
                context.emit("add-todo", {
                    id: Date.now(),
                    value: todo.value,
                    complete: false,
                });

                hasError.value = false;
                todo.value = "";
            }
        }

        return {
            todo,
            addTodo
        }
    }
}
</script>

부모 컴포넌트 (v-on으로 이벤트 받기)

<template>
	<!-- v-on으로 이벤트 받기 -->
    <TodoSimpleForm @add-todo="addTodo"></TodoSimpleForm>
   
    <div class="card">
        <div class="card-body" v-for="(list, index) of todos" :key="index">
            <span>
                {{list.id}}
            </span>
            <p>
                {{list.value}}
            </p>
        </div>
    </div>
</template>
<script>
import { ref } from "vue";
import TodoSimpleForm from "./components/TodoSimpleForm.vue"

export default {
    name: 'App',
    components: {
        TodoSimpleForm
    },
    setup() {
        const todos = ref([]);

        const addTodo = (todo) => {
            todos.value.push(todo)
        }

        return {
            todos,
            addTodo
        }
    }
}
</script>

 

 

Vue2

자식 컴포넌트 ($emit으로 이벤트 전달)

<template>
    <article v-if="isLayerOpen">
        <h2>팝업</h2>
        <button @click="closeDetailLayer">팝업닫기</button>
    </article>
</template>
<script>
	
    export default {
        name: "childLayer",
        props: {
        	isLayerOpen: {
            	type: Boolean,
                default: true,
                required: true,
            }
        },
        methods: {
            closeDetailLayer() {
            	this.$emit("closeDetailLayer");
            }
        }
    }
</script>​

부모 컴포넌트 (v-on으로 이벤트 받기)

<template>
   	<ChildLayer ::is-layer-open="isLayerOpen" @close-detail-layer="closeDetailLayer($event)"></ChildLayer>
</template>
<script>
	
    export default {
        name: "parent",
        data() {
            return {
                isLayerOpen: false,
            }
        },
        
        methods: {
            closeDetailLayer() {
            	this.isLayerOpen = true;
            }
        }
    }
</script>

 

 

2. 부모컴포넌에서 자식컴포넌트로 데이터를 전달할때는 props

Vue3 (== Vue2)

props는 vue2와 동일하다.
간단하게 정리하면 부모에서 데이터를 자식으로 넘길때 사용하는데 타입은 String, Number, Boolean, Array, Object, Function, Promise 이 될 수 있다.

중요한것은 props는 부모컴포넌트 > 자식컴포넌트로만 전달! 자식컴포넌트에서 직접적으로 바꾸지 않기

자식 컴포넌트 (여기서 쓰이는 todos는 부모에서 전달받은 데이터!)

<template>
    <div class="card">
        <div class="card-body" v-for="(list, index) of todos" :key="index">
            <span>{{list.id}}</span>
            <span>{{list.value}}</span>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        todos: {
            type: Array,
            required: true
        }
    }
}
</script>

<style>

</style>

부모 컴포넌트 (데이터 넘겨주기 :자식에서 쓸 이름="부모에 있는 데이터 이름")

<template>
    <TodoSimpleForm @add-todo="addTodo"></TodoSimpleForm> 
    
    <!-- 여기서 v-bind를 이용하여 데이터를 넘기기 -->
    <TodoList :todos="todos"></TodoList>
</template>
<script>
import { ref } from "vue";
import TodoSimpleForm from "./components/TodoSimpleForm.vue"
import TodoList from "./components/TodoList.vue"

export default {
    name: 'App',
    components: {
        TodoSimpleForm,
        TodoList
    },
    setup() {
        const todos = ref([]);

        const addTodo = (todo) => {
            todos.value.push(todo)
        }

        return {
            todos,
            addTodo
        }
    }
}
</script>
반응형