본문 바로가기
개발/Vue.js

[Vue.js] TypeError: Cannot read properties of undefined (reading '__ob__') 해결방법

by 방구쟁이 2022. 10. 27.
728x90

시작점

프로젝트 당시 페이지를 이동하면 이전 페이지의 Vue를 destroy하는 과정에서 다음과 같은 에러가 발생했다. 

Observer 속성인 __ob__를 읽는 도중 undefined

 

그럼 다음 에러를 해결해보자.

 

프로젝트 구조

프로젝트 구조는 다음과 같이 Vue 안에 컴포넌트가 있었다.

상품리스트 Vue
 └ 상품별 뱃지 Vue component
편성표 Vue
 .
 .
 .

 

상품 리스트 Vue Template

<script type="text/x-template" id="GoodsListTpl">
    <div :id="id">
    		.
        	.
        	.
        <Badge :data="item" />
        	.
        	.
        	.
    </div>
</script>

 

상품별 뱃지 Vue Component

<script type="text/javascript">
    Vue.component('Badge',{
        props : ['data'],

        data : function(){
            
        },

        template : '#BadgeTpl'
    });
</script>

<script type="text/x-template" id="BadgeTpl">
    <div class="badge">
        <template v-if="data.status == 'deadline'">
            <div class="tagImg"><img :src="$uiPath+'images/common/tag.png'" alt=""></div>
        </template>
            .
            .
            .
    </div>
</script>

 

 

상품리스트 Vue가 destroy될때 우리가 기대하는 Vue의 라이프사이클은 다음과 같다.

  1. beforeDestroy 상품 리스트
  2. beforeDestroy 상품별 뱃지
  3. destroyed 상품별 뱃지
  4. deestroyed 상품 리스트

하지만 위에 기대와는 다르게 상품별 뱃지 컴포넌트를 destroyed 하는 과정에서 Type에러가 발생하였다.

 

원인이 무엇일까?

 바로 컴포넌트에서 data 선언이 잘못 되었기 때문이다. 각각의 컴포넌트마다 각자의 데이터를 관리해야 한다. 컴포넌트 data를 함수형이 아닌 오브젝트로 생성하면 단일 인스턴스가 속성을 공유하여 data 값을 참조하기 때문이다.

 Vue는 Observer를 통해 의존성 변화를 감지하고 업데이트를 수행합니다. Observer는 객체 내부에 __ob__ 속성을 할당하고 인스턴스 data의 Key들을 반응형으로 만듭니다. 하지만 컴포넌트 data가 함수형이 아닌 오브젝트로 생성하면 단일 인스턴스가 속성을 공유하여 data 값을 참조하기 때문에 뱃지 컴포넌트 data만의 __ob__ 속성을 찾을 수 없다.

Badge 컴포넌트의 data가 함수형이지 않은 경우 _data가 undefined이며 __ob__ 속성이 없다.

 

해결 방법

 컴포넌트에서는 객체 리터럴로 선언하는 것이 아니라 함수형으로 return 값을 통해 반환해야 한다. 또한 return을 이용하면 각 컴포넌트끼리 속성을 공유하지 않고 분리하여 관리할 수 있다.

<script type="text/javascript">
    Vue.component('Badge',{
        props : ['data'],

        data : function(){
            return {
            	// return 값을 통해 리터럴을 반환
            }
        },

        template : '#BadgeTpl'
    });
</script>

Badge 컴포넌트 _data 및 __ob__ 속성

 

컴포넌트를 사용할 경우에는 data를 함수형으로 return 값으로 반환해주자.

 

틀린 내용 및 자세한 설명이 있다면 공유 부탁드려요!

감사합니다. 

 

참고 자료

https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

https://v3.ko.vuejs.org/guide/data-methods.html#data-%E1%84%89%E1%85%A9%E1%86%A8%E1%84%89%E1%85%A5%E1%86%BC

https://hj-tilblog.tistory.com/78

https://handhand.tistory.com/258

728x90

'개발 > Vue.js' 카테고리의 다른 글

프로젝트에 Vue.js를 적용한 경험  (0) 2023.04.03
Vue Cli 4.x (Vue3)에서 vue-router 사용하기  (0) 2021.08.13
Vue.js란?  (0) 2021.07.06
vue.$NextTick이란?  (0) 2021.07.04

댓글