异步代码中 useRouter 返回 undefined

375 阅读1分钟

先看个简单的示例

<script lang="ts" setup>
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'

function getData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('data')
    }, 1000)
  })
}

onMounted(async () => {
  await getData()
  const router = useRouter()
  console.log(router) // undefined
})
</script>

useRouter的实现原理是通过vueprovideinject来实现,具体看下inject的实现原理:

vuejs/core/packages/runtime-core/src/apiInject.ts

instance由于是在异步函数中,所以instancenull(为什么instance为null可见我的这篇文章getCurrentInstance何时会返回null),再看下currentApp

vuejs/core/packages/runtime-core/src/apiCreateApp.ts

currentAppcurrentInstance类似,默认值为null,在runWithContent函数执行时会被赋值,runWithContent执行结束后又会被重置null。官方文档中有提供说明runWithContent的用法,上面这个示例并不涉及,所以currentApp当作null处理。

所以最终inject(routerKey)返回undefined

tips:

当前作用域下是否可以使用inject,官方特意提供了一个函数用来判断

验证一下:

<script lang="ts" setup>
import { onMounted, hasInjectionContext } from 'vue'

function getData() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('data')
    }, 1000)
  })
}

onMounted(async () => {
  await getData()
  console.log(hasInjectionContext())
})
</script>