这篇文章主要介绍了vue是异步渲染的原因有哪些的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue是异步渲染的原因有哪些文章都会有所收获,下面我们一起来看看吧。
原因:可以提升性能。如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染;所以为了性能考虑,Vue会在本轮数据更新后,再去异步更新视图,而不是每当有数据更新,就立即更新视图。
1、nextTick()的原理及作用
nextTick确保我们所操作的DOM是更新之后的。
(1)应用场景:在视图更新之后,基于新的视图进行操作。
在数据变化后执行的某个操作,而这个操作需要使用随数据变化而变化的DOM结构的时候,这个操作就需要放在
nextTick()
的回调函数中。如果在created()钩子进行DOM操作,created()中dom还没有渲染,一定要放在
nextTick()
的回调函数中。Vue采用了数据驱动视图的思想,但是在一些情况下,仍然需要操作DOM。有时候,DOM1的数据发生了变化,而DOM2需要从DOM1中获取数据,那这时就会发现DOM2的视图并没有更新,这时就需要用到了
nextTick
了。
(2)原理:
nextTick 的核心是利用了如 Promise 、MutationObserver、setImmediate、setTimeout的原生 JS 方法来模拟对应的微/宏任务的实现;
本质是为了利用 JS的这些异步回调任务队列来实现 Vue 框架中自己的异步回调队列;
本质是对JS执行原理事件循环的一种应用
nextTick 是典型的将底层JS执行原理应用到具体案例中的示例,引入异步更新队列机制的原因∶
如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染。所以为了性能考虑,Vue 会在本轮数据更新后,再去异步更新视图。而不是每当有数据更新,就立即更新视图。
为了在数据更新操作之后操作DOM,我们可以在数据变化之后立即使用
nextTick(callback)
;nextTick()将回调延迟到下一个事件循环开始时执行, 这样回调函数会在DOM更新完成后被调用,就可以拿到最新的DOM元素了。
当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新才会进行必要的DOM更新。
(3) vue的降级策略
Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替,进行降级处理。降级处理的目的都是将flushCallbacks
函数放入微任务或者宏任务队列,等待下一次事件循环时来执行
实际刷新队列是有可能在本次事件循环的微任务中刷新的,也可能是在下一个事件循环中刷新的。这取决于代码当前执行的环境,如若当前执行环境支持promise,那么nextTick内部实际会用Promise去执行,那么队列刷新就会在本次事件循环的微任务中去执行。
优先选择微任务的原因:在微任务中更新队列是会比在宏任务中更新少一次UI渲染的。
2、为何Vue采用异步渲染
vue是组件级更新,组件内有数据变化时,该组件就会更新。例:this.a = 1、this.b=2(同一个watcher)
(1)原因:如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染。所以为了性能考虑,Vue 会在本轮数据更新后,再去异步更新视图。而不是每当有数据更新,就立即更新视图。
(2)过程:
Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 中 观察到数据变化的 watcher 推送进这个队列。
如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据,避免不必要的计算和Dom操作。
而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
3)源码解析:
数据变化时,通过notify通知watcher进行更新操作;
通过subs[i].update依次调用watcher的update(未更新视图);
将watcher放到队列中,在queueWatcher会根据watcher的id进行去重(多个属性依赖一个watcher),如果队列中没有该watcher就会将该watcher添加到队列中(未更新视图);
通过nextTick异步执行flushSchedulerQueue方法刷新watcher队列(更新视图);
关于“vue是异步渲染的原因有哪些”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“vue是异步渲染的原因有哪些”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。