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>
반응형
'Vue > Vue3' 카테고리의 다른 글
[Vue3] 컴포넌트간 통신하기 vue2의 eventbus, Vue3에서는 mitt (emitter) (0) | 2021.12.15 |
---|---|
[Vue2 vs Vue3] vue에 있는 ref 접근하기 ! this.$ref 사용하기 (template refs) (0) | 2021.12.07 |
[Vue.config.js & SCSS] Vue2 / Vue3 에서 global scss 연결하기 (0) | 2021.12.06 |
[Vue2 vs Vue3] 기본내용정리 3 (computed와 methods) (0) | 2021.12.06 |
[Vue2 vs Vue3] 기본내용정리1 (Fragment / setup / ref,reactive) (0) | 2021.12.06 |