美文网首页
vue-nextTick原理

vue-nextTick原理

作者: 梦行乌托邦 | 来源:发表于2020-08-08 10:06 被阅读0次

vue官网:
可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

例如,当你设置 vm.someData = 'new value',该组件不会立即重新渲染。当刷新队列时,组件会在下一个事件循环“tick”中更新。多数情况我们不需要关心这个过程,但是如果你想基于更新后的 DOM 状态来做点什么,这就可能会有些棘手。虽然 Vue.js 通常鼓励开发人员使用“数据驱动”的方式思考,避免直接接触 DOM,但是有时我们必须要这么做。为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 Vue.nextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。

src/core/util/next-tick.js

页面初始化会执行这一段代码。

let timerFunc
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  const p = Promise.resolve()
  timerFunc = () => {
    p.then(flushCallbacks)
    if (isIOS) setTimeout(noop)
  }
  isUsingMicroTask = true
} else if (!isIE && typeof MutationObserver !== 'undefined' && (
  isNative(MutationObserver) ||
  MutationObserver.toString() === '[object MutationObserverConstructor]'
)) {
  let counter = 1
  const observer = new MutationObserver(flushCallbacks)
  const textNode = document.createTextNode(String(counter))
  observer.observe(textNode, {
    characterData: true
  })
  timerFunc = () => {
    counter = (counter + 1) % 2
    textNode.data = String(counter)
  }
  isUsingMicroTask = true
} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

flushCallbacks的作用是:执行nextTick回调
1、如果支持promise
flushCallbacks放入Promise.then,即加入微任务队列
如果是ios则还是用setTimeout方式
2、如果支持MutationObserver(监听dom变化,也是微任务)
创建一个简单的文本节点并修改它,触发执行flushCallbacks
这里主要是为了用到它的微任务特性
3、如果支持setImmediate(比setTimeout耗时少)
4、用setTimeout宏任务

vue进行DOM更新内部也是调用nextTick来做异步队列控制。而当我们自己调用nextTick的时候,它就在更新DOM的那个microtask后追加了我们自己的回调函数,从而确保我们的代码在DOM更新后执行,同时也避免了setTimeout可能存在的多次执行问题。

调用nextTick方法会把回调存入callbacks中

export function nextTick (cb?: Function, ctx?: Object) {
  let _resolve
  callbacks.push(() => {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  if (!pending) {
    pending = true
    timerFunc()
  }
  // $flow-disable-line
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}

以上,会触发timerFunc方法,这个方法就是文章上面通过层层判断是否支持某些特性得出的延迟执行的函数。

总结:
用callbacks来存放所有的nextTick回调函数,数据更新后会调用nextTick去渲染dom,然后我们自己定义的nextTick回调会被放入callbacks,所以这个自定义回调就会在dom渲染后执行

相关文章

  • vue-nextTick原理

    vue官网:可能你还没有注意到,Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列...

  • vue-nextTick

    https://www.jianshu.com/p/a7550c0e164f 应用场景 在Vue生命周期的crea...

  • Vue-nextTick

    因为dom实时发生变化,要异步更新

  • 华与华方法(8)传播第一原理

    传播三大原理: 第一原理:刺激反射原理 第二原理:播传原理 第三原理:信号能量原理。 一、刺激反射原理 所有传播都...

  • 大数据相关

    hadoop原理 spark原理 kafka原理 数据仓库部分 Hadoop原理 MapReduce的原理默认根据...

  • js call apply instanceof 实现原理

    call原理 apply原理 instanceof原理

  • 《影响力》读后感

    全书主要围绕六大原理开展,分别是互惠原理,承诺和一致原理,社会认同原理,喜好原理,权威原理,以及稀缺原理。全文结构...

  • Today面试

    Runloop 底层原理Kvo 底层原理ARC 底层原理 如何实现GCD 底层原理Block 底层原理Aut...

  • iOS底层原理:weak的实现原理

    iOS底层原理:weak的实现原理iOS底层原理:weak的实现原理

  • 原理原理原理

    忙碌的一天,英语还有一个小题,明天完善,明天加油背诵英语对话 ,今天个人简历也有了大体框架,明天完善一下,加油。 ...

网友评论

      本文标题:vue-nextTick原理

      本文链接:https://www.haomeiwen.com/subject/uilqdktx.html