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 ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ •ํ™•ํžˆ ์ฐพ๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค.๐Ÿค˜

๋ฐ˜์‘ํ˜•