Vue的nextTick源码解析

2/16/2022 vue

nextTick 支持两种形式使用方式:

  1. 回调函数形式。
  2. 如果当前环节支持 Promise,还支持 Promise.then 的形式。
let pending = false,
timeFunc,
callbacks=[];

//cb:执行的回调函数,context:执行上下文参数
function nextTick(cb,context){
  let _resolve=null;
  callbacks.push(()=>{
    if(cb){
      try{
        cb.call(context)
      }catch(e){
        handleError(e,ctx,'nextTick)
      }
    }else if(_resolve){
      _resolve(context)
    }
  })
  if(!pending){
    pending=true;
    timeFunc()
  }
  if(!cb&&typeof Promise !== "undefind"){
    rteurn new Promise(resolve=>_resolve=resolve)
  }
}

let isUsingMicroTask = false;
if (typeof Promise !== 'undefined' && isNative(Promise)) {
  //判断1:是否原生支持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]'
)) {
  //判断2:是否原生支持MutationObserver
  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)) {
  //判断3:是否原生支持setImmediate
  timerFunc = () => {
    setImmediate(flushCallbacks)
  }
} else {
  //判断4:上面都不行,直接用setTimeout
  timerFunc = () => {
    setTimeout(flushCallbacks, 0)
  }
}

function flushCallbacks () {
  pending = false
  const copies = callbacks.slice(0)
  callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

nextTick(()=>{
  console.log("nextTick callback")
})
nextTick().then(()=>{
  console.log("nextTick Promise")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
Last Updated: 3/16/2022, 6:38:11 PM