vue.js/vue.js 기능

[vue.js] object(객체) 에 없는 데이터 변경 감지 vm.$set

반응형

서론

지난번 글 hjh0827.tistory.com/41 에서 배열(array)로 데이터 바인딩을 작성하였다. 해당 내용은 개인적 개발로 작성한것이므로 이번에는 obejct로 간단하게 데이터 바인딩에 대해 작성해보도록 하겠다.

 

상황

  1. 부모 컴포넌트 + 자식 컴포넌트
  2. 부모 컴포넌트에서 data로 선언된 obejct를 자식 컴포넌트로 prop
  3. 부모 컴포넌트에서 obejct 데이터 바인딩 시 자식 컴포넌트 변경 확인

vue.js에서 가장 중요한 데이터 바인딩 처리를 하기 위해 위의 상황을 생성하였다. 해당 구조는 vue.js에서 흔하게 볼수 있는 구조이다. 보통 부모 컴포넌트에서 선언한 데이터가 변경시 해당 데이터를 상속받는 자식 컴포넌트는 해당 데이터를 바인딩 해야한다.

 

case 1. vm.items,.indexOfItem= newValue

ex) this.childText.text = this.textData

childText 라는 object에 text 라는 attribute로 textData를 value로 넣었다.

 

소스

parent.vue

<template>
  <div id="parent">
    <h1>parent</h1>
    <input v-model="textData" type="text">
    <br><input type="button" value="childText text set" @click="changeChildText">
    <child :is-alive="isAlive" :prop-child-text="childText" @childDeadEvent="onDeadEvent" />
  </div>
</template>

<script>
import child from '~/components/child'

export default {
  components: { child },
  data () {
    return {
      textData: '',
      childText: {}
    }
  },
  methods: {
    changeChildText () {
      this.childText.text = this.textData
    }
  }
}
</script>

child.vue

<template>
  <div class="child">
    <h1>child</h1>
    propChildText.text: {{ propChildText.text }}
    <br>
    childText: {{ childText }}
    <br>
  </div>
</template>

<script>
export default {
  props: {
    propChildText: {
      type: Object,
      required: true,
      default: null
    }
  },
  computed: {
    childText () {
      console.log('================================')
      console.log(this.propChildText)
      return this.propChildText
    }
  }
}
</script>

<style scoped>
    .child {
        padding: 10px;
        background-color: skyblue;
    }
</style>

테스트

 

parent.vue에서 childText 데이터가 추가되었지만 child.vue에 데이터가 전달되지 않는다.

와이?????????????????????

 

해당 이유는 vue.js 공식 홈페이지에 나와있다.

kr.vuejs.org/v2/guide/list.html#%EA%B0%9D%EC%B2%B4-%EB%B3%80%EA%B2%BD-%EA%B0%90%EC%A7%80%EC%97%90-%EA%B4%80%ED%95%9C-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD

 

리스트 렌더링 — Vue.js

Vue.js - 프로그레시브 자바스크립트 프레임워크

kr.vuejs.org

해당 내용을 기반으로 case2를 진행하겠다.

 

case2. Vue.set(object, propertyName, value)

ex) this.$set(this.childText'text2'this.textData)

this.$set 을 이용하여 this.childText 의 obejct에 text2라는 attribute로 textData를 value로넣었다.

 

소스

parent.vue

<template>
  <div id="parent">
    <h1>parent</h1>
    <input v-model="textData" type="text">
    <br><input type="button" value="childText text2 set" @click="changeChildText2">
  </div>
</template>

<script>
import child from '~/components/child'

export default {
  components: { child },
  data () {
    return {
      textData: '',
      childText: {}
    }
  },
  methods: {
    changeChildText2 () {
      this.$set(this.childText, 'text2', this.textData)
      console.log(this.childText)
    }
  }
}
</script>

child.vue

<template>
  <div class="child">
    <h1>child</h1>
    propChildText.text2: {{ propChildText.text2 }}
    <br>
    childText: {{ childText }}
    <br>
  </div>
</template>

<script>
export default {
  props: {
    propChildText: {
      type: Object,
      required: true,
      default: null
    }
  },
  computed: {
    childText () {
      console.log('================================')
      console.log(this.propChildText)
      return this.propChildText
    }
  }
}
</script>

<style scoped>
    .child {
        padding: 10px;
        background-color: skyblue;
    }
</style>

테스트

 

parent.vue에서 등록한 데이터가 child.vue로 정상적으로 데이터 바인딩 되는것을 볼 수 있다.

 

정리

처음에 vue.js를 시작할때 this.obejct.attribute= value 로 데이터 set 하였다. 그럼 자식 컴포넌트로 데이터가 전달되지 않아서 object를 선언할때 사용할 attribute를 전부 선언해줬었다.

ex) childText: {

        text: '',

        text2: '',

        ...

    }

 

하지만 개발하다보면 필요한 attribute을 전부 선언하여 사용하기 힘들뿐 아니라 object에 전부 넣으려면 attribute가 길어지는 경우가 있다. 그럴땐 잊지말고 $set으로 attribute을 추가하여 사용하도록 하자

반응형