从 Composition API 源码分析 getCurrentInstance() 为何返回 null

4Ark at 
从 Composition API 源码分析 getCurrentInstance() 为何返回 null的配图

而第二次调用的内部是这样的,这时候它已经变成了 null

可以看到 getCurrentInstance() 的内部非常简单,只是将 currentInstance 给返回出来了,而这个变量显然是在外部定义的,那为什么两次调用,它的值就发生了变化呢?

我们留意到断点进来的文件是:vue-composition-api.esm.js,那我们直接在 node_modules 下打开这个文件,先搜索一下有哪些地方修改了 currentInstance 这个变量,根据上图就能看到是通过 setCurrentInstance() 方法来修改,于是我们搜索一下这个方法的调用:

可以看到一共有四处(其中一处是定义),但是光靠肉眼看也很难看出来什么,所以还是老方法,在每个调用之前加一个断点(是的,我们可以直接修改 node_modules 下的代码来进行调试),然后我们发现第一次调用是在 activateCurrentInstance

这时候我们仔细看看这个方法的内部,就能看出些端倪:

  1. 上图显示 preVm 是一个 null
  2. vm 是一个 Vue 的实例
  3. 执行完 fn(vm) 后,又将 preVm 传入到 setCurrentInstance() 去了

所以,我们看看这个 fn(vm) 内部是什么,搜索 activateCurrentInstance() 的调用,发现一个很可疑的地方:

很明显这里就是执行组件 setup() 函数的地方,再结合上图来看,我们得出结论:

  1. 在执行组件 setup() 函数前,先把当前实例存放起来
  2. 然后执行组件 setup() 函数时, setup() 函数内部自然就能通过 getCurrentInstance() 访问当前实例了
  3. 等执行完 setup() 后,又将 currentInstance 重置回 null 去了(注意是同步执行 setup()
  4. 后面 setup() 内部的异步代码再去调用 getCurrentInstance() ,其实已经是 null

如果还不太理解的同学,建议先补一下 JavaScript 的:事件循环、同步、异步、宏任务、微任务这些概念。