NextTick 是作什麼到?vue
來自 Vue 官網講述: 在下次 DOM 更新循環結束以後執行延遲迴調。在修改數據以後當即使用這個方法,獲取更新後的 DOM。git
是否似曾類似github
Vue.nextTick(() => {})
this.$nextTick(() => {})
在 vue 中 created 函數鉤子函數執行的時候DOM 其實並未進行任何渲染,因此得放在 nextTick 中去獲取 dom,與其對於得生命週期鉤子函數是 mounted
BUT 中 Vue 中 for 渲染 dom 就算是中 mounted 調用 nextTick也不能獲取到具體到 dom,爲何
如今來一探究竟promise
打印的是什麼,請先思考【下面有答案】多線程
console.log(1)
setTimeout(() => {
console.log(8)
}, 2000)
setTimeout(() => {
console.log(3)
Promise.resolve().then(() => {
console.log(4)
})
setTimeout(() => {
console.log(6)
}, 3000)
}, 1000)
new Promise((resolve, reject) => {
console.log(5)
resolve()
}).then(() => {
console.log(7)
})
console.log(2)
複製代碼
js 是單線程執行,固然,如今又有了一個 worker 創造了多線程環境,可是 worker 受限不少, js 執行是有一個執行棧,主要分了,宏任務(macro-task)和 微任務(micro-task)dom
宏任務有那些異步
微任務有那些函數
// 執行流程
(執行一個宏任務,產生宏任務,入棧)
↑
--------↑------- 宏任務 ←--—--
| | |
| | |
| | |
| ↓ | 沒有
| 微任務 ------
| |↘
| |(執行全部微任務過程當中產生微任務,繼續執行)
| |
| | 有 執行完因此微任務
| |
|___________↓
--------------------↓------------------
直到棧爲空
複製代碼
咱們在來看上面的問題oop
我去.......,上面這一大堆和 NextTick 有什麼關係?
還真有點關係,看源碼,我只剪取了主要部分,源碼來自 wepypost
// 微任務
let microTimerFunc
// 宏任務
let macroTimerFunc
// 默認不用宏任務,由於微任務到優先級高於宏任務
let useMacroTask = false
// 判斷 setImmediate 能不能使用
if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
// 能使用註冊宏任務
macroTimerFunc = () => {
setImmediate(flushCallbacks)
}
// 是否支持 MessageChannel
} else if (typeof MessageChannel !== 'undefined' && (
isNative(MessageChannel) ||
// PhantomJS
MessageChannel.toString() === '[object MessageChannelConstructor]'
)) {
// 經過命名通道來通訊
const channel = new MessageChannel()
const port = channel.port2
channel.port1.onmessage = flushCallbacks
macroTimerFunc = () => {
port.postMessage(1)
}
} else {
macroTimerFunc = () => {
setTimeout(flushCallbacks, 0)
}
}
// 判斷是否可使用 Promise ie 8 如下不能吧.....
if (typeof Promise !== 'undefined' && isNative(Promise)) {
const p = Promise.resolve()
// 註冊微任務
microTimerFunc = () => {
p.then(flushCallbacks)
}
} else {
// 若是不存在,微任務註冊宏任務
microTimerFunc = macroTimerFunc
}
/** 複製代碼
執行流程就是
宏任務 檢測 setImmediate ----- 不能 ----> 降級 MessageChannel ------不能-----> 降級 setTimeout
微任務 Promise ---- 不能 ---> 微任務註冊微宏任務
上面的 flushCallbacks 就是你要執行的函數
在 Vue 整個 nextTick 的做用
// 盜用官方的一個例子
Vue.component('example', {
template: '<span>{{ message }}</span>',
data: function () {
return {
message: '未更新'
}
},
methods: {
updateMessage: function () {
this.message = '已更新'
console.log(this.$el.textContent) // => '未更新'
this.$nextTick(function () {
console.log(this.$el.textContent) // => '已更新'
})
}
}
})
// 在 updateMessage 方法中,更新數據,當即獲取更新後的 dom 是獲取不到的,因此得把獲取 dom 加到事件隊列的棧,異步獲取更新後的dom
複製代碼
主線程更新前 ---> 遇到宏任務或微任務 ---> 放入棧 ---> 主線程執行完成,更新完成 ----> 執行棧 ---- > 獲取更新後的dom