부모 state 변경하기 (prop)Vue32022. 10. 17. 17:51
Table of Contents
Prop으로 function 넘기기
- 기존에는 React로 개발을 해왔기 때문에 부모에서 미리 자신의 상태를 변화시킬 function을 작성해서 props로 넘겨주고 자식에서 props로 받은 function을 이용해서 부모의 상태를 변경하는 방식이 익숙했었다.
- Vue.js도 prop으로 부모의 상태를 변경시키는 function을 받아서 자식 컴포넌트가 해당 function을 호출해서 부모의 상태를 변경하는 방식이 가능하다.
- 아래 예시를 살펴보자!
button 사용할 때
부모 컴포넌트
- 부모 컴포넌트에서 미리 자신의 상태를 변경시키는 function을 작성해서 자식 컴포넌트에게 넘겨준다.
<template>
<div>
<h1>{{ state }}</h1>
<Child :setState="setState" />
</div>
</template>
<script>
import Child from "./components/Child.vue";
export default {
name: "App",
data() {
return {
state: 0,
};
},
components: { Child },
methods: {
setState: function () {
this.state++;
},
},
};
</script>
자식 컴포넌트
- 자식 컴포넌트는 부모 컴포넌트로부터 function을 받아서 이벤트리스너로 사용하면 끝!
<template>
<button @click="setState">Parent State ++</button>
</template>
<script>
export default {
props: {
setState: Function,
},
};
</script>
<style>
</style>
input 사용할 때
부모 컴포넌트
- 자신의 상태와 상태를 변화시키는 함수를 prop으로 자식에게 내려준다
<template>
<h1>{{ state }}</h1>
<EmitAndModel :setState="setState" :state="state" />
</template>
<script>
import EmitAndModel from "./components/EmitAndModel.vue";
export default {
data() {
return {
state: "",
};
},
components: { EmitAndModel },
name: "App",
methods: {
setState(e) {
console.log(e.target.value);
this.state = e.target.value;
},
},
};
</script>
자식 컴포넌트
- 부모로부터 받은 부모의 상태를 v-bind를 이용해 input에 바인딩하고 input 이벤트의 이벤트 리스너로 부모의 상태를 변화시키는 함수를 이용하자!
<template>
<span>Parent Input</span><input :value="state" @input="setState" />
</template>
<script>
export default {
props: {
setState: Function,
state: String,
},
};
</script>
<template><span>Parent Input</span><input v-model="state" /></template>
<script>
export default {
props: {
state: String,
},
};
</script>
+++주의 사항
- 위와 같은 방법으로 부모의 상태를 변경하는 함수를 prop으로 받아서 자식이 바꾼다 생각해서 two-way-binding이라 오해할 수 있지만! 자식 컴포넌트가 prop으로 받아서 v-on에 넣는 부모의 상태를 변경하는 함수의 this가 부모의 this로 바인딩 되어서 넘어가는 것이다!!
- 자식이 직접 바꾸는게 아니다!
- 아래 예시를 꼭 보자..! 다음에 또 까먹을게 확실하다
부모 컴포넌트
- 아래처럼 부모 컴포넌트에 a라는 상태를 추가하고 자식 컴포넌트 input의 v-on에 prop으로 넘겨줄 부모의 상태를 변화하는 함수에 this.a를 console을 찍어보자!
- 자식 컴포넌트에서 사용하는 setState의 this가 부모 컴포넌트의 this로 binding 되어있다면 자식 컴포넌트의 input에 값을 입력할 때마다 "I'm parent"가 콘솔에 출력될 것이다!
<template>
<h1>{{ state }}</h1>
<TestVue :setState="setState" :state="state" />
</template>
<script>
import TestVue from "./components/TestVue.vue";
export default {
data() {
return {
state: "",
a: "I'm parent",
};
},
components: { TestVue },
name: "App",
methods: {
setState(e) {
console.log(this.a);
this.state = e.target.value;
},
},
};
</script>
자식 컴포넌트
<template>
<span>Parent Input</span><input :value="state" @input="setState" />
</template>
<script>
export default {
props: {
setState: Function,
state: String,
},
};
</script>
- 위 이야기를 왜했냐면 내가 아래와 같이 멍청한 짓을 했기 때문이다!!
- 부모의 상태를 prop으로 받아서 v-model로 엮으려고 했다
<template><span>Parent Input</span><input v-model="state" /></template>
<script>
export default {
props: {
state: String,
},
};
</script>
- 왜 그렇게 생각했나면 자기의 state를 input에 two-way-binding 할 때, v-model로 연결할 때 아래의 코드를
<input :value="state" @input="state=$event.target.value" />
- syntax sugar를 이용해 v-model을 이용해 짧게 썻기 때문에 될 줄 알았다.
<input v-model="state" />
- 결론은 부모의 상태를 prop으로 받아서 자식에서 v-model로 two-way-binding 하면 절대로 되지 않는다. 애초에 prop을 변경하면 안되기 때문이다. 부모로부터 부모의 상태를 변경하는 함수를 받아서 이벤트 핸들러로 사용해도 된 이유는 그 함수의 this가 바인딩 되어있기 때문이지만 부모의 상태를 prop으로 받아서 v-model을 써버리면 그냥 자기 prop을 바인딩해서 값을 바꾼다는 것과 다르기 없기 때문이다!
그래서 이글 왜씀?
- 결론은 부모의 상태를 바꿀땐 emit이랑 v-model 이용해서 공식문서에서 하란대로 하라고 ㅋㅋ 위에 방법 쓰지말라는거임 ㅅㄱ
'Vue3' 카테고리의 다른 글
Slot (0) | 2022.10.20 |
---|---|
중요! 부모 state 변경하기 (emit + v-model) (0) | 2022.10.19 |
Array 렌더링 (v-for) (0) | 2022.10.17 |
조건부 렌더링 (v-if/v-else/v-else-if/v-show) (1) | 2022.10.17 |
Computed/Watch (0) | 2022.10.17 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!