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