Vue 원본 퀴즈 2: Vue.nextTick 사용법
5065 단어 Vue 소스 분석
공식 설명
다음 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
})
}
}
})()