Front-End

[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();

 

 

[연관자료]

 

[Vuetify.js] treeview 사용법 정리

vuetify.js 라이브러리의 treeview를 사용하는 방법에 대한 정리입니다. v-treeview API는 아래 링크를 참고하면 되고, Props, Functions, Events 등의 정보를 확인할 수 있습니다. v-treeview API API for the v-..

playground.naragara.com

 

[Vuetify.js] 서버에서 불러온 데이터로 Treeview 노드 items Array 데이터 생성 방법

신규프로젝트에서 트리뷰 작업을 해야하는 상황에 놓였다. 그리고 어제 vuetify.js 의 트리뷰 컴포넌트에 대한 기술검토를 하였다. 그리고 오후 부터 트리노드 생성을 위해 데이터베이스로부터 불

playground.naragara.com

 

[REFERENCE]

 

2022년 명절이 눈앞이다.

새해 복 많이 받자!!! (Happy new Year)

 

 

Leave a Reply

error: Content is protected !!