41、为何Vue采用异步渲染(核心的方法就是nextTick)?

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)过程:
  1. Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 中 观察到数据变化的 watcher 推送进这个队列。
  2. 如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据,避免不必要的计算和Dom操作。
  3. 而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。

(3)源码解析:

  1. 数据变化时,通过notify通知watcher进行更新操作;
  2. 通过subs[i].update依次调用watcher的update(未更新视图);
  3. 将watcher放到队列中,在queueWatcher会根据watcher的id进行去重(多个属性依赖一个watcher),如果队列中没有该watcher就会将该watcher添加到队列中(未更新视图);
  4. 通过nextTick异步执行flushSchedulerQueue方法刷新watcher队列(更新视图);
 
  • 21
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值