Vue $nextTick 两种写法的差异

代码

vue 的nextTick的主要代码如下:

// 触发回调数组里面所有的回调
function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}
// 延迟触发
macroTimerFunc = () => {
    setImmediate(flushCallbacks)
}
// 第一个参数回调函数,第二个参数是执行函数上下文
export function nextTick (cb?: Function, ctx?: Object) {
  let _resolve
  // 将回调push到回调数组中 在下一次nexttick的时候统一触发
  callbacks.push(() => {
    if (cb) {
      try {
        cb.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (_resolve) {
      _resolve(ctx)
    }
  })
  if (!pending) {
    pending = true
    if (useMacroTask) {
      macroTimerFunc()
    } else {
      microTimerFunc()
    }
  }
  // 如果没有回调函数则返回一个promise对象 作为回调函数
  if (!cb && typeof Promise !== 'undefined') {
    return new Promise(resolve => {
      _resolve = resolve
    })
  }
}
// 设置$nextTick 方法
Vue.prototype.$nextTick = function (fn: Function) {
    return nextTick(fn, this)
}
复制代码

今天做一个播放webrtc视频功能的时候碰到了一个小问题,很奇怪所以稍微研究了下vue的nextTick。

问题

问题描述

在设置video标签的srcObject属性的时候,当我使用

this.$nextTick(() => {
	if (this.$refs.videoNode) {
		this.$refs.videoNode.srcObject = this.videoStream;
	}
});
复制代码

去设置的时候我发现视频是空白的,经过尝试视频流和video标签都是是没有问题的。那就只有调用的时机的问题了。 然后查看nextTick的代码之后选择第二种方式

this.$nextTick().then(() => {
	if (this.$refs.videoNode) {
		this.$refs.videoNode.srcObject = this.videoStream;
	}
})
复制代码

发现视频是正常播放的。 然后想起来我video标签是放在弹出层dialog中的,dialog会去修改里面元素的位置代码如下:

this.$nextTick(() => {
    let moveNodeRef = this.$refs.moveNodeRef;
    if (moveNodeRef) {
      if (this.parentNode) {
        this.parentNode.appendChild(moveNodeRef);
      } else if (this.appendToBody) {
        document.body.appendChild(moveNodeRef);
      }
    }
  });
复制代码

在nextTick的回调函数的中去把元素插入到其他的元素中。于是就尝试了下在设置完video的srcObject后再去移动video元素发现视频卡在了移动时候的那一帧画面。

原因

nextTick会在一次事件循环之后一起调用。给video的srcObject的赋值在dialog的移动dom之前,所以导致video不能播放视频,而第二种写法是promise,promise是异步的,会在本次事件循环结束之后才会调用,因此会在dom移动之后才会触发,因此没有问题。

结论

看似两种写法没有多大的区别,但是调用的先后顺序还是有很大的区别的!

转载于:https://juejin.im/post/5c383c92518825253208f083

你可能感兴趣的:(javascript,ViewUI)