vue / $nuxtTick() 사용하기

삼안기·2022년 9월 4일
0

Vue

목록 보기
1/1
post-thumbnail

전달인자
Object, Function

비동기로 처리되는 javascript의 특성상 data가 업데이트 되고 난 직후 UI 갱신 시 vue가 DOM을 찾지 못하는 경우가 있다. 이때 callback 함수인 $nextTick()을 사용한다.
$nextTick() 의 콜백함수 안에서 DOM을 조작하면, 데이터를 가지고 화면을 그리기 전에 DOM이 먼저 생성되어 트리를 찾지 못하는 오류를 막을 수 있다.

예시 1

<template>
  <div id="app">
    <div v-for="item in list" :key="item">
      <div :id="bindId(item)"/>    <!-- 2 -->
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      list: []
    };
  },
  created () {
    for (let i = 0; i < 100; i++) {
      this.list.push(i); // 1
    }
    const dom = document.getElementById('item-0'); // DOM을 찾지 못해 에러발생
    dom.style.backgroundColor = 'red';
  },

  methods: {
    bindId (item) {
      return 'item-' + item; // 3
    }
  }
};
</script>

이 때 $nextTick() 을 사용함으로서 data 갱신과 UI를 그린 후 실행되어 dom.style.backgroundColor = 'red'; 적용한다.

this.$nextTick(function () {
  const dom = document.getElementById('item-0');
  dom.style.backgroundColor = 'red';
});

다만 UI가 그려질 때 까지 dom.style.backgroundColor = 'red'; 가 실행되지 않기 때문에 일정 지연이 발생한다.

예시 2

<template>
  <div class="hello">
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'One'
    };
  },
  mounted () {
    this.msg = 'Two';

    this.$nextTick(() => {
      this.msg = 'Three';
    });
  }
};
</script>

mounted에 선언된 Two는 화면에 그려질까? 아니다.
OneThree 만 그려진다. 그 이유는 data가 실행되고 브라우저에 권한을 넘겨주는 대신 바로 callback이 실행되기 때문에 Two는 그려지지 않는다.

But with nextTick
, we skip steps 2 and 3! Instead of passing over control after the first vDOM update, Vue calls the callback immediately
, which prevents the browser from updating until the callback is finished. In this example, that means "Two" is never actually displayed.

$forceUpdate

Vue의 상태는 변경되었으나 화면에 변경된 상태가 반영되지 않는 경우 이 메서드를 사용하며 다시 렌더링하며 반영시킬 수 있다.하지만 렌더링은 작업 자체가 비용이 많이 들기 때문에 과도하게 사용할 시 애프리케이션의 성능이 하락할 수 있다.

<div id="app">
  <h1>{{Math.random()}}</h1>
  <button @click="update">Force Update</button>
</div>

methods:{
  update(){
    this.$forceUpdate();
  }
}
profile
문제를 해결해야지

0개의 댓글