this.$nextTick平时怎么使用的?说说它的原理?
① vue的DOM更新是异步更新的(为什么设计成异步更新?因为比如我们在created钩子函数里面100次循环设置this.xxx=i,若不是异步那岂不是需要触发100次响应dom更新,这里也是优化方案之一),比如我们在执行了this.xxx=1,这个时候去拿dom上的xxx值结果还是原来的值而非刚刚设置的1,此时我们需要使用this.$nextTick在callback中拿就没问题了
② 原理:
源码1905行~源码2007行
源码1984行 执行nextTick后会将cb全部Push进callbacks全局数组收集任务起来
源码1999行 这里执行了一个timerFunc函数 这个声明过程在源码1930行到1982行 这里作了
1.是否支持Promise 浏览器方法兼容
2.是否支持MutaionObserver DOM监听方案
3.是否支持setImmediate Node环境
4.最后使用setTimeout(flushCallbacks,0) 做了这么多判断其实是利用了js事件循 环(event loop)机制来将当前需要执行的cb放到事件任务队列中 在下一次事件循环中再执行 后面会记录下事件循环相关东西
源码1910行 这里使用for循环分别来执行之前push进来的函数(也就是我们cb回调)
js事件循环Event Loop是基于js是单线程操作 同一时间只能执行一个任务 而js主线程拥有一个“执行栈”以及一个“任务队列” 参考网上说法:js执行主线程任务 遇到需要执行异步任务时会将此刻的异步任务推进“任务队列”,当主线程执行完毕后会“清空当前执行栈”,按照先入先出的顺序来执行任务队列里面的任务
异步任务分为:宏任务(macrotasks)和微任务(microtasks)
宏任务(macrotasks)一般包含:
1.I/O操作 浏览器支持 node支持
2.setTimeout 浏览器支持 node支持
3.setInterval 浏览器支持 node支持
4.setImmediate 浏览器不支持 node支持
5.requestAnimationFrame 浏览器支持 node不支持
微任务(microtasks)一般包含:
1.process.nextTick 浏览器不支持 node支持
2.MutationObserver 浏览器支持 node不支持
3.Promise.then catch finally 浏览器支持 node支持
4.async await 浏览器支持 node支持
例如1:
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
});
console.log('script end');
我的理解是这4句代码整体是一个js主线程 从上往下执行
第一句:打印出"script start"
第二句:遇到异步任务且setTimeout属于宏任务 压入异步任务宏队列(若存在多个则按先入先出)
第三句:遇到异步任务且Promise属于微任务 压入异步任务微队列(若存在多个则按先入先出)
第四句:打印出"script end"
至此js主线程上task执行完毕 那么需要执行异步任务 而异步任务中微任务先于宏任务执行
打印出"promise1"
打印出"promise2"
最后执行宏任务 打印出"setTimeout"
例如2:
console.log('script start');
setTimeout(function() {
console.log('setTimeout1');
}, 0);
setTimeout(function() {
console.log('setTimeout2');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
Promise.resolve().then(function(){
console.log('promise内部')
})
}).then(function() {
console.log('promise2');
}).then(function(){
console.log('promise3')
});
console.log('script end');
// script start
// script end
// promise1
// promise内部
// promise2
// promise3
// setTimeout1
// setTimeout2
例如3:
new Promise(resolve => {
resolve();
})
.then(() => { // 4行
new Promise(resolve => {
resolve();
})
.then(() => {
console.log(777); // 9行
})
.then(() => {
console.log(888); // 12行
});
})
.then(() => {
console.log(666); // 16行
});
这种嵌套promise可以这样理解 程序先执行第一个promise.then即第4行(压入队列16行) 接到遇到promise.then该分支没的其他主代码执行 则执行promise.then即第9行(压入队列12行) 执行完后又返回来执行promise.then的第二个即16行 然后再执行内部的第二个promise.then即12行
// 777
// 666
// 888