woolta

vue watch 속성에서 Object와 같이 중첩된 값의 변경을 감지하자

wooltaUserImgb00032 | vue | 2019-12-13

watch

vue 에서 watch속성은 값이 변경될때 이에 대한 부수 효과 (비동기 통신을 통한 재호출, 변경된 값에 대한 DOM조작 등등 ) 을 처리할대 유용하게 사용되는 속성입니다. 그러나 기본타입이 아닌 중첩된 같은 값의 변경을 감지할때는 문제가 있습니다.

Object 데이터 watch

우선 다음과 같이 parent 컴포넌트와 child 컴포넌트를 작성해주도록 하겠습니다. 각 컴포넌트의 역활은 다음과 같습니다.

  • parent 컴포넌트 : data 오브젝트를 자식컴포넌트로 내려주고 버튼 클릭시 data 오브젝트의 count를 증가 시켜줍니다.
  • children 컴포넌트 : parent 로 받은 data 오브젝트의 count를 보여주고 data 속성을 watch 로 변경시 console.log 를 보여주도록 합니다.

parent 컴포넌트

<template>
    <div>
        <button @click="increase">숫자 증가</button>
        <children :parent-data="data"/>
    </div>
</template>

<script>
    import Children from './children';

    export default {
        name: 'parent',
        components: {Children},
        methods: {
            increase() {
                this.data.count = this.data.count + 1;
            },
        },
        data() {
            return {
                data: {
                    count: 0,
                },
            };
        },
    };
</script>

<style scoped></style>

child 컴포넌트

<template>
    <div>
        <div>
            <span>카운트 {{parentData.count}}</span>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'children',
        watch: {
            parentData(newData) {
                console.log(`data change ${newData}`)
            },
        },
        props: {
            parentData: {
                type: Object,
                default() {
                    return {};
                },
            },
        },
    };
</script>

<style scoped></style>

위에서 작성한 컴포넌트를 실행시켜본 결과는 다음과 같습니다.

https://image.woolta.com/deepPrev.gif

예상했던것처럼 data의 count 를 변경할 경우 이에대해 변경된 값으로 바꾸어 보여주지만 watch 속성에서는 변경된 것을 감지하지 못하고 있습니다.

watch - deep 속성

이러한 Object의 중첩된 값의 변경을 감지하고 싶다면 아주 간단하게 watch의 속성인 deep 을 추가해 주면 감지할 수 있습니다. 해당 속성을 적용하여 child 컴포넌트를 수정해 주도록 하겠습니다.

deep 속성을 적용한 child 컴포넌트

<template>
    <div>
        <div>
            <span>카운트 {{parentData.count}}</span>
        </div>
    </div>
</template>

<script>
    export default {
        name: 'children',
        watch: {
            parentData: {
                deep: true,
                handler(newData) {
                    console.log(`data change ${newData.count}`)
                },
            },
        },
        props: {
            parentData: {
                type: Object,
                default() {
                    return {};
                },
            },
        },
    };
</script>

<style scoped></style>

위의 수정한 컴포넌트를 보면 중첩된 데이터의 감지를 위해 deep 속성을 추가 된 것을 볼 수 있습니다. 이때 handler 함수는 해당 값이 변경될 경우 호출되는 함수입니다. 즉 맨처음 선언한 파라미터가 없는 watch 속성은 아래 코드의 단축표현 입니다.

 watch: {
            parentData {
                handler(newData){
                       console.log(`data change ${newData}`)
               }
            },
        },

이제 수정한 결과를 확인해보도록 하겠습니다.

https://image.woolta.com/deepAfter.gif

짜잔 다음과 같이 정상적으로 변경된 것을 감지한 것을 확인할 수 있습니다. :)

참조

Copyright © 2018 woolta.com

gommpo111@gmail.com