nextTick原理

使用场景

  1. 想要操作基于最新数据生成的Dom,就需要使用nextTick
onSubmit(formName: string) {
			(this.$refs[formName] as Form).validate((valid) => {
				if (valid && this.validateRateTotal()) {
					this.$emit('showSplitterModel', this.splitterForm, 'success');
				} else {
					this.$nextTick(() => {
						const errorElement = document.getElementsByClassName(
							'el-form-item__error'
						)[0] as HTMLElement;
						errorElement.scrollIntoView({ block: 'center' });
					});
				}
			});
		}

前置知识

  • nextTick的作用相当于异步执行传入的函数

  • 同步任务:js是单线程的,单线程就是事件任务的执行要排队,前一个任务结束,才能进入下一个任务

  • 步骤:

    1. 所有的同步任务都在主线程执行,形成一个执行栈
    2. 除了主线程之外,还有一个任务队列;一旦异步任务有了运行结果,就把其回调函数作为一个任务放到任务队列中
    3. 一旦执行栈中的所有同步任务完成,就会读取任务队列,将里面的任务添加到执行栈中执行
    4. 主线程不断的重复第三步
  • 异步任务

    1. 异步任务的执行都是通过任务队列来执行的。异步任务分类两大类:宏任务和微任务(参考文章)
    2. 宏任务:setTimeout、setInterval、postMessage、MessageChannel、 网络请求IO、DOM、鼠标、键盘、滚动事件、页面渲染
    3. 微任务:Promise.then、 MutationObserve、process.nexttick
  • 实现原理
    1. 将传入的回调函数包装成异步任务,异步任务又分为微任务和宏任务。为了尽快执行所以优先选择微任务(why:按照事件循环的执行顺序,执行下一次宏任务之前会进行一次UI渲染,等待的时间会比微任务多的多)
    2. 提供四种异步方法:promise.then、mutationObserver、setImmediate、setTinmeout(fn, 0)
    3. 主流程:将传入的回调函数包装一下存入callbacks数组中,调用timerFunc函数,在其中去遍历执行callbacks函数,这样就实现了nextTick函数异步执行传入函数
    4. 源码解读

  • 将传入的回调函数处理一下,放入callbacks数组

    • 利用pending来保证执行一个事件循环只执行一次timerFunc

    • 最后判断一下是否传入了回调函数且支持Promise
      nextTick原理_第1张图片

    • 优先执行promise。Promise是个微任务,因此timerFunc就变成了异步执行

    • 若不支持Promise,在执行MutationObserver。让counter的值在0和1之间变化,再把变化的counter设置为文本节点的内容,这样observer就会监测到文本节点的变化,就会调用flushCallbacks。MutationObserver是个微任务,因此timerFunc就变成了异步执行

    • 若不支持MutationObserver,在执行setImmediate。只兼容IE10以上的浏览器,其他浏览器不支持,宏任务,资源消耗小

    • 若不支持setImmediate,在执行setTimeout。兼容IE10以下,宏任务,资源消耗大
      nextTick原理_第2张图片

    • 判断是否原生支持;如果浏览器内置函数调用实例方法的话,就会返回一个native code

    • flushCallbacks函数遍历callbacks数组的拷贝并执行其中的回调
      isNative

    • 为什么要拷贝callbacks:nextTick回调中还有可能会调用nextTick,就有可能向callbacks中添加回调,就有可能一直循环。nextTick回调中的nextTick应该放在下一次的循环里面
      nextTick原理_第3张图片

你可能感兴趣的:(Vue,nextTick,javascript,前端,vue.js)