先看个简单的示例
<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的实现原理是通过vue的provide和inject来实现,具体看下inject的实现原理:
vuejs/core/packages/runtime-core/src/apiInject.ts
instance由于是在异步函数中,所以instance是null(为什么instance为null可见我的这篇文章getCurrentInstance何时会返回null),再看下currentApp
vuejs/core/packages/runtime-core/src/apiCreateApp.ts
currentApp跟currentInstance类似,默认值为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>