当前位置: 代码迷 >> 综合 >> vue2.x($nextTick)
  详细解决方案

vue2.x($nextTick)

热度:47   发布时间:2023-12-19 11:54:36.0

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
例如3new 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