Vue 원본 퀴즈 2: Vue.nextTick 사용법

5065 단어 Vue 소스 분석
Vue.nextTick
공식 설명
다음 DOM 업데이트 주기가 끝나면 지연 콜백을 실행합니다.데이터를 수정한 후 즉시 이 방법을 사용하여 업데이트된 DOM을 가져옵니다.
주해
Vue의 Dom 트리 업데이트는 보통 비동기 리셋에서 이루어집니다. 이곳의 비동기 리셋은promise나setTimeout을 사용할 수 있습니다.이로 인해 업데이트된 Dom 구조를 동기화할 수 없습니다. 데이터 상태 업데이트가 완료된 후에 Vue는 Dom 트리를 즉시 업데이트하는 것이 아니라 다음 이벤트 순환에서 업데이트되기 때문입니다.(뭘 물어볼지 물어보지 마세요. 문서에 분명히 적혀 있어요)
Vue는 Dom 업데이트를 완료한 후 호출Vue.nextTick하기 때문에 업데이트된 Dom을 얻을 수 있습니다.nextTick는 모든 Vue 실례를 통일된 곳에서 처리하는 전체적인 방법이다.이 방법은 주로 데이터 상태에 변화가 발생한 후에 호출한다. 예를 들어data의 변화, mutation의 호출 후 등이다.예를 들어 페이지에 Vue 실례 a, b가 있는데 js는 이 두 실례의 데이터를 수정한 후에 각각 vue.nextTick 호출했고 페이지가dom 업데이트가 끝난 후에 두 개의 리셋 함수가 호출될 것이다.
원본 해독: 중국어 주석 부분을 보십시오
export const nextTick = (function () {
  //     dom            
  const callbacks = []
  //    dom     timerFunc         
  let pending = false
  let timerFunc

  function nextTickHandler () {
    pending = false
    const copies = callbacks.slice(0)
    callbacks.length = 0
    for (let i = 0; i < copies.length; i++) {
      copies[i]()
    }
  }

  //  eventloop        
  if (typeof Promise !== 'undefined' && isNative(Promise)) {
    var p = Promise.resolve()
    var logError = err => { console.error(err) }
    timerFunc = () => {
      p.then(nextTickHandler).catch(logError)

      if (isIOS) setTimeout(noop)
    }
  } else if (typeof MutationObserver !== 'undefined' && (
    isNative(MutationObserver) ||
    // PhantomJS and iOS 7.x
    MutationObserver.toString() === '[object MutationObserverConstructor]'
  )) {
    // use MutationObserver where native Promise is not available,
    // e.g. PhantomJS IE11, iOS7, Android 4.4
    var counter = 1
    var observer = new MutationObserver(nextTickHandler)
    var textNode = document.createTextNode(String(counter))
    observer.observe(textNode, {
      characterData: true
    })
    timerFunc = () => {
      counter = (counter + 1) % 2
      textNode.data = String(counter)
    }
  } else {
    // fallback to setTimeout
    /* istanbul ignore next */
    timerFunc = () => {
      setTimeout(nextTickHandler, 0)
    }
  }

  return function queueNextTick (cb?: Function, ctx?: Object) {
    let _resolve
    callbacks.push(() => {
      if (cb) {
        try {
          cb.call(ctx)
        } catch (e) {
          handleError(e, ctx, 'nextTick')
        }
      } else if (_resolve) {
        _resolve(ctx)
      }
    })
    if (!pending) {
      pending = true
      timerFunc()
    }
    if (!cb && typeof Promise !== 'undefined') {
      return new Promise((resolve, reject) => {
        _resolve = resolve
      })
    }
  }
})()

좋은 웹페이지 즐겨찾기