[Vue.js] 커스텀 컴포넌트(custom component) 구현시 부모와 자식 컴포넌트 사이에 데이터 동기화(sync) 하는 방법
자식 컴포넌트에서 데이터를 가공해야한다면?
트리뷰를 예로 들어본다. 트리뷰를 바닥페이지에서 공통으로 사용할 수도 있고,
팝업창 혹은 다이얼로그창에서도 사용할 수 있음으로 공통으로 사용할 수 있도록 컴포넌트로 만들었다.
부모 컴포넌트 뷰는 다음과 같다.
부모 컴포넌트는 왼쪽에 트리를 구현하고 오른쪽에 트리를 클릭했을 때 상세정보를 불러오도록 구현되었다.
[Main.vue]
<v-row>
<v-col cols="12" sm="3">
<TreeView ref="treeRef"
:treeItems="data.treeItems"
@treeClicked="refsTreeKey"/>
</v-col>
</row>
<v-divider vertical></v-divider>
<v-col cols="12" sm="9">
<v-row>
<v-card-title>
<p>제품 정보</p>
<v-btn
dark
color="cyan darken-1"
@click="save();">신규등록</v-btn>
</v-card-title>
</v-row>
..........이하생략
import TreeView from '@/views/components/tree/TreeView.vue';
export default {
name: 'Product',
components: {
TreeView,
},
methods: {
refsTreeKey(data) {
alert(data);
},
.....이하 생략
생성한 자식 컴포넌트뷰(Treeview.vue)는 다음과 같다.
<template>
<v-treeview
rounded
activatable
item-key="id"
:open-all = true
:items="itemsTree"
@update:active="selected"
dense
></v-treeview>
</template>
<script>
export default {
name: 'TreeView',
props: {
treeItems: {
type: Array, default: () => []
},
},
data: () => ({
itemsTree: [],
}),
mounted() {
console.log(`activated: ${JSON.stringify(this.treeItems)}`);
this.itemsTree = this.getTreeNestedArray(this.treeItems);
},
methods: {
getTreeNestedArray(array) {
const topLevel = 0;
const treeNodes = [];
console.log(`받은 자료: ${JSON.stringify(array)}`);
array.forEach((item) => {
if (item.treeDepth === topLevel) {
const node = {};
node.id = item.treeId;
node.name = item.treeName;
node.children = this.makeNode(array, topLevel + 1, item.treeId);
treeNodes.push(node);
}
});
// console.log(`${JSON.stringify(treeNodes)}`);
return treeNodes;
},
makeNode(array, level, parentId) {
const childNodes = [];
array.forEach((item) => {
if (item.treeDepth === level && item.parentId === parentId) {
const node = {};
node.id = item.treeId;
node.name = item.treeName;
node.children = this.makeNode(array, level + 1, item.treeId);
childNodes.push(node);
}
});
return childNodes;
},
selected(key) {
if (key[0] !== undefined) {
console.log(`${JSON.stringify(key[0])}`);
this.$emit('treeClicked', key[0]);
}
},
clearInit() {
alert(1);
},
},
}
</script>
부모컴포넌트에서 데이터를 가공 후 자식 컴포넌트뷰에서 props로 받으면 정상적으로 바로 적용되었다.
그러나 트리를 구현하기 위한 네이스트 어레이를 만들기 위한 함수를 자식 컴포넌트뷰에 두기 위해
mounted() 생명주기에서 함수를 호출하였지만 먹히지 않았다.
created()에서 호출해도 먹히지 않았다.
mounted() {
console.log(`activated: ${JSON.stringify(this.treeItems)}`);
this.itemsTree = this.getTreeNestedArray(this.treeItems);
},
이럴 때 해결방법이 있다. 그것은 바로 watch를 사용하는 것이다.
부모 컴포넌트에서 전달하는 :treeItems=”data.treeItems” 를 watch에서 관찰하는 것이다.
이때 핸들러를 사용해야하고 ,immediate는 true를 주면된다.
해당 스크립트는 다음과 같다.
watch: {
treeItems: {
handler(newValue){
this.itemsTree = this.getTreeNestedArray(this.treeItems);
},
immediate: true,
}
},
체크박스형 트리뷰를 구현했을 때 트리의 노드를 선택했을 때 이벤트 활성화 방법 역시 watch를 이용해서 구현가능하다.
// 자식 컴포넌트에서
watch: {
selectItem : {
handler(newValue){
this.$emit('refsKey', this.selectItem);
},
immediate: true,
},
},
부모 컴포넌트에서 자식 컴포넌트의 함수를 호출하는 방법
$refs를 이용하여 접근가능하다. 자식 콤포넌트를 호출하는 부분에 ref 명을 지정 후 접근하면된다.
this.$refs.treeRef.clearInit();
[연관자료]
[REFERENCE]
2022년 명절이 눈앞이다.
새해 복 많이 받자!!! (Happy new Year)