• Vue中$nextTick原理


    Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。

    如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。

    然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。

    Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

    也就是说我们在设置this.msg = 'some thing'的时候,Vue并没有马上去更新DOM数据,而是将这个操作放进一个队列中;

    如果我们重复执行的话,队列还会进行去重操作;等待同一事件循环中的所有数据变化完成之后,会将队列中的事件拿出来处理。

      这样做主要是为了提升性能,因为如果在主线程中更新DOM,循环100次就要更新100次DOM;

    但是如果等事件循环完成之后更新DOM,只需要更新1次。

      为了在数据更新操作之后操作DOM,我们可以在数据变化之后立即使用Vue.nextTick(callback);这样回调函数会在DOM更新完成后被调用,就可以拿到最新的DOM元素了

    Vue源码中对   $nextTick()   分析:

    可以看出这边代码其实是做了四个判断,对当前环境进行不断的降级处理,尝试使用原生的Promise.thenMutationObserversetImmediate

    上述三个都不支持最后使用setTimeout;

    降级处理的目的都是将flushCallbacks函数放入微任务(判断1和判断2)或者宏任务(判断3和判断4),等待下一次事件循环时来执行。

    MutationObserver是Html5的一个新特性,用来监听目标DOM结构是否改变,也就是代码中新建的textNode;

    如果改变了就执行MutationObserver构造函数中的回调函数,不过是它是在微任务中执行的。

    总结:

      把回调函数放入callbacks等待执行

      将执行函数放到微任务或者宏任务中

      事件循环到了微任务或者宏任务,执行函数依次执行callbacks中的回调

      再回到我们开头说的setTimeout,可以看出来nextTick是对setTimeout进行了多种兼容性的处理,宽泛的也可以理解为将回调函数放入setTimeout中执行;

      不过nextTick优先放入微任务执行,而setTimeout是宏任务,因此nextTick一般情况下总是先于setTimeout执行,我们可以在浏览器中尝试一下:

    原文链接地址:https://mp.weixin.qq.com/s/ZOlgBRs6pwUBIzljcCZSfQ

    文章来源于前端壹读 ,作者谢小飞

  • 相关阅读:
    你自己不优秀,就算认识再多优秀人又有何用
    史玉柱和他老同学的一段故事
    哪有雪中送碳,都是锦上添花
    围城之困
    心已死,梦前行
    一位销售高手逼单经历!
    Python--函数return多个值
    Python--内置函数
    Python--小程序
    Python--递归
  • 原文地址:https://www.cnblogs.com/swt-axios/p/12834958.html
Copyright © 2020-2023  润新知