FrontEnd/Vue.js

[Vue.js] ref undefined일 경우 해결 방법 (this.$nextTick)

김평범님 2022. 3. 22. 21:30
반응형

vuejs ref undefined일 때 this.$nextTick이용하기

🏷️Vue ref란?

Vue에서 특정 컴포넌트나 HTML에 접근을 하고 싶을 때는 ref속성을 이용해서 접근이 가능하다.

먼저 아래의 코드로 예시를 보자.

 

/page/ref.vue

<template>
    <div>
        <h1>상위컴포넌트 입니다.</h1>
        <button @click="componentClick">하위 컴포넌트 클릭 이벤트 호출</button>
        <refComponent ref="refComponent" style="margin:30px 0 0 0;"/>
    </div>
</template>
<script>
    import refComponent from '~/components/refComponent.vue';

    export default {
        components: {
            refComponent
        },
        data() {
            return {}
        },
        methods: {
            componentClick: function () {
                this.$refs.refComponent.clickCount();
            }
        }
    }
</script>

/components/refComponent.vue

<template>
  <div>
      <h3>하위 컴포넌트 입니다.</h3>
      <h5>상위컴포넌트 클릭 Count : {{count}}</h5>
  </div>
</template>
<script>
export default {
  data() {
    return{
      count:0
    }
  },
  methods: {
      clickCount: function() {
        this.count = this.count + 1;
      }
  }
}
</script>

ref.vue에서 refComponent에 접근해서 하위 컴포넌트의 function을 실행하는 코드이다.

 

이럴 경우 하위 컴포넌트에 ref를 이용해서 컴포넌트 명에 접근한다

그다음 해당 컴포넌트에 methods에 등록된 clickCount를 호출해서 숫자를 올리는 코드이다.

 

ref를 이용해서 하위 컴포넌트 접근하기

이렇듯 ref를 이용하면 해당 컴포넌트에 손쉽게 접근할 수 있다.

 

 

 

 

 

 

 

🚩ref 사용 시 주의 사항 

ref로 하위 컴포넌트로 접근하려면 아래 코드로 접근이 가능하다.

this.$refs.컴포넌트이름

 

하지만, 이때 확인해야 하는 점은 

refs 속성에 접근하려면 해당 컴포넌트가 랜더링(rendering)이 완료된 후 접근이 가능하다.

 

이러한 속성 때문에 created 주기에서는 this.$refs가 undefined가 뜨며

mounted 주기에 들어와야 ref로 랜더링이 되어야 접근이 가능한 것을 알 수 있다.

 

 

/page/ref.vue

<template>
    <div>
        <h1>상위컴포넌트 입니다.</h1>
        <button @click="componentClick">하위 컴포넌트 클릭 이벤트 호출</button>
        <refComponent ref="refComponent" style="margin:30px 0 0 0;"/>
    </div>
</template>
<script>
    import refComponent from '~/components/refComponent.vue';

    export default {
        components: {
            refComponent
        },
        data() {
            return {}
        },
        created() {
            console.log('created');
            console.log(this.$refs.refComponent);
        },
        mounted() {
            console.log('mounted');
            console.log(this.$refs.refComponent);
        },
        methods: {
            componentClick: function () {
                this.$refs.refComponent.clickCount();
            }
        }
    }
</script>

mounted 후에 this.$refs에 접근이 되는 화면

 

 

 

 

 

 

 

🤔v-if에서 ref 사용 오류

랜더링(rendering) 이 되어야 접근이 가능하다는 특징 때문에

v-if 조건이 적용되지 않을 때 ref에 접근하는 코드를 쓰면 다시 undefined가 떠서

이때는 v-show로 코드를 바꿔서 ref에 접근을 하면 된다.

 

오늘 나의 경우는 라이브러리를 이용해서 라이브러리 자체적으로

v-if로 코딩이 되어있어서내가 변경이 불가능한 경우가 발생했다.🙉

 

 

 

 

 

😃 this.$nextTick() 이용하기

이렇듯 비동기로 처리되는 과정 중에서 Data 업데이트 직 후에

DOM이 변경되기도 전에 DOM에 접근하려고 하면 찾지 못하는 undefined 이슈가 발생한다.

 

이를 해결하기 위해 나온 게 this.$nextTick이다

$nextTick 콜백 함수를 이용하면

데이터가 모두 갱신된 다음에 그다음 함수를 수행한다.

 

<template>
    <div>
        <h1>상위컴포넌트 입니다.</h1>
        <button @click="componentClick">하위 컴포넌트 클릭 이벤트 호출</button>
        <refComponent ref="refComponent" style="margin:30px 0 0 0;"/>
    </div>
</template>
<script>
    import refComponent from '~/components/refComponent.vue';

    export default {
        components: {
            refComponent
        },
        data() {
            return {}
        },
        async created() {
            console.log('created');
            await this.$nextTick();
            console.log(this.$refs.refComponent);
        },
        mounted() {
          console.log('mounted');
          console.log(this.$refs.refComponent);
        },
        methods: {
            componentClick: function () {
                this.$refs.refComponent.clickCount();
            }
        }
    }
</script>

 

기존 코드에서 created앞에 async를 넣어주고

await this$nextTick(); 다음에 ref를 호출했다.

 

await this.$nextTick 호출

이런 식으로 호출했을 경우 console에서 정확히 ref 컴포넌트를 정확히 찾는 것을 확인했다.🤘

반응형