본문 바로가기

programming/Vue

[Vue] textarea 조건부 랜더링시 focus 이동 안되는 케이스 해결 -> $ref.focus() & nextTick() 메소드

[TODO]

입력 Form 에서 사용자가 Yes / No 중 Yes 라고 답하면 상세 내역을 적기 위한 textarea 를 보여주어야 한다

 

 

[WHAT I DONE]

- "YES" 버튼을 클릭시 setAnswerY 메소드를 실행하여 this.answer_y = true 로 세팅

- this.answer_y 값이 true 이면 <textarea v-if="answer_y">

- textarea 요소가 보이고 focus 도 자동으로 이동

 

 

[첫번째 시도]

setAnswerY() {
    this.answer_n = false
    this.answer_y = true
    // 마우스 커서 이동
    this.setFocus('inputText')
},

setFocus(item) {
	this.$refs[item].focus()
},

 

✔️ 결과

answer_y=true 로 바꾸는 즉시 DOM이 업데이트 되지 않아서 $ref 요소를 찾을 수 없음

Because Vue is trying to optimize and batch changes, it won't immediately update the DOM when we set isEditing to false. So when we call focusOnEdit(), the "Edit" Button has not been rendered yet.

 

 

[두번째 시도]

- setTimeout을 이용한 시간차

setAnswerY() {
    this.answer_n = false
    this.answer_y = true
    // 마우스 커서 바로 이동
    setTimeout(() => {
    	this.setFocus('inputText')
    }, 200)
    this.setFocus('inputText')
},

setFocus(item) {
    this.$refs[item].focus()
    this.$nextTick(() => {
    const itemRef = this.$refs[item]
    	itemRef.focus()
    })
},

 

✔️ 결과

구현은 되었으나 임시방편같은 느낌,,

 

 

[세번째 시도] -> BEST❣️

- Vue의 nextTick() 메소드 사용

setAnswerY() {
  this.answer_n = false
  this.answer_y = true
  // 마우스 커서 바로 이동
  this.setFocus('inputText')
},

setFocus(item) {
  this.$nextTick(() => {
    const itemRef = this.$refs[item]
    itemRef.focus()
  })
},

 

✔️ 결과 

Vue의 nextTick() 메소드를 사용하여 DOM이 재렌더링 된 이후 $ref.focus 잡도록 처리

Instead, we need to wait until after Vue undergoes the next DOM update cycle. To do that, Vue components have a special method called $nextTick(). This method accepts a callback function, which then executes after the DOM updates.

 

 

[추가 시도]

 

v-show & v-if 의 차이점

 

v-show는 일단 내부적으로 렌더링은 하되 display : none / block 으로 조정

v-if 상태값에 따라 그때그때 렌더링 여부가 결정됨

하지만, v-show를 써도 마찬가지로 DOM이 업데이트 될 때까지 nextTick() 메소드로 기다려야함