props로 부모와 자식간에 데이터를 전달 하는것을 보았는데 부모컴포넌트와 자식컴포넌트 이렇게 하나의 depth만 존재한다면 그렇게 불편하지 않을수 있다. 하지만 1depth가 아닌 2depth 부모 - 자식 - 자식의 자식 이런식으로 구성이 된다면 props로 넘기는 방식이 까다로울 것이다. provide, inject를 이용하면 좀 더 쉽게 처리가 가능하다.
먼저 PanelView와 FormView를 만들어보았다. PanelView는 form의 형태를 보여주기만 하는 용도이다.
FormView는 입력만 받는 용도인데 예시를 위하여 내부에 InputView를 또 만들어 실제로는 이곳에서 데이터를 입력받을 예정이다. 일반적으로 본다면 양쪽 다 props로 form의 데이터를 넘겨야 하고 해당 데이터를 변경하는 메소드를 FormView에 보낸후 FormView는 다시 InputView에 넘겨주어야 하는 상황이다.
이러한 내용을 props가 아닌 provide와 inject를 통하여 구현하여 보자.
<template>
<div>
<PanelView></PanelView>
<hr />
<FormView></FormView>
</div>
</template>
<script>
import PanelView from "@/views/PanelView.vue";
import FormView from "@/views/FormView.vue";
export default {
components: {
FormView,
PanelView,
},
data() {
return {
form: {
name: "홍길동",
age: null,
email: "",
},
};
},
methods: {
changeForm(name, value) {
this.form[name] = value;
},
},
provide() { // 해당 메소드가 자식들에게 전달해주는 내용을 담고 있다.
return {
form: this.form, //
changeForm: this.changeForm,
};
},
};
</script>
<style></style>
<template>
<div>
<p>name : {{ form.name }}</p>
<p>age : {{ form.age }}</p>
<p>email : {{ form.email }}</p>
</div>
</template>
<script>
export default {
inject: ["form"], // 부모에서 전달 받은 form
};
</script>
<style></style>
<template>
<InputView></InputView>
</template>
<script>
import InputView from "@/views/InputView.vue";
export default {
components: {
InputView,
},
};
</script>
<style></style>
<template>
<div>
<p>
name :
<input type="text" name="name" :value="form.name" @input="changeInput" />
</p>
<p>
age :
<input type="number" name="age" :value="form.age" @input="changeInput" />
</p>
<p>
email :
<input
type="text"
name="email"
:value="form.email"
@input="changeInput"
/>
</p>
</div>
</template>
<script>
export default {
inject: ["form", "changeForm"], // 부모에서 전달 받은 요소들
methods: {
changeInput(e) {
const name = e.target.name;
const value = e.target.value;
this.changeForm(name, value);
},
},
};
</script>
<style></style>
이러한 형태로 사용하면 props로 일일히 넘겨주지 않고 편하게 부모데이터를 처리할 수 있게 된다.
참고로 form 자체를 넘겨 이런식으로 사용해도 실제 RootView.vue의 form 데이터의 email이 변경은 되지만 이런 사용이 좋은지는 고민해볼 문제이다. 기본적으로 vue.js의 props의 취지는 read-only이다. 하지만 object를 넘김으로 아무래도 object는 reference라 v-model로 변경이 되는 것으로 이해 되는데 과연 사용이 된다고 해서 vue.js 본연의 취지를 어긋나는게 좋은 방법인지는 모르겠다. 또한 이런식으로 작성한 코드가 늘어난다면 유지보수적인 측면에서도 그닥 좋아보이지는 않아보인다. 물론 InputView.vue의 역할은 input 입력이기 때문에 얼핏 보면 v-model로 변경하는게 이상하지 않아 보일수도 있겠지만... 그것은 해당 프로그램이 사용불가가 될때까지 InputView.vue에서만 form 데이터를 변경하는 경우에만 용인되는 이야기일것 같다. 다른 곳에서 form데이터를 v-model로 변경해버리는 순간 유지보수는 더 어려워질 가능성이 크기 때문에 설령 object가 v-model로 직접변경이 가능하더라도 사용하지 않는것이 좋다고 말하고 싶다. 물론 v-model로 coputed를 통한 변경은 괜찮다.