问题诞生
在pinia等状态管理库当中,是无法使用useRouter获取router的,这样无法调用router.push进行路由跳转
import { defineStore } from "pinia";
import {useRouter} from 'vue'
export default defineStore("faultReport", () => {
const router = useRouter() //为undefined
});
源码层面
function useRouter() {
return inject(routerKey);
}
可以见,在useRouter本质是使用的vue3当中的inject与provide。但为什么获取不到,答案在createRouter里面
function createRouter(options) {
....
const router = {
install(app){
app.provide(routerKey, router);
}
}
....
}
在日常配置vue-router当中,一般都会在main.js文件当中使用app.use(router),
而这个router又需要调用createRouter,此时,这个app是全局跟组件,既
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);//根组件
app.use(router)//调用router里的install方法
此方式相当于在跟组件注册了router,这样在各大子组件使用useRuter就获取到router了。
而pinia不在各大组件setup当中,自然就无法获取到router,这就是根本原因。
什么是各大组件的setup
setup就是组件的上下文,由一个vue的api可以获取,这又涉及到vue的源码
getCurrentInstance
这就是getCurrentInstance后获取的组件上下文,type里面就含有当前组件的信息,
而provide的值就存在CurrentInstance.provides当中,只不过vue-router使用Symbol类型值进行设置。 这样任何一个子组件就都可以通过useRouter获取到router.
function provide(key, value) {
if (!currentInstance) {
{
warn$1(`provide() can only be used inside setup().`);
}
} else {
let provides = currentInstance.provides;
const parentProvides = currentInstance.parent && currentInstance.parent.provides;
if (parentProvides === provides) {
provides = currentInstance.provides = Object.create(parentProvides);
}
provides[key] = value;
}
}
function inject(key, defaultValue, treatDefaultAsFactory = false) {
const instance = currentInstance || currentRenderingInstance;
if (instance || currentApp) {
const provides = instance ? instance.parent == null ? instance.vnode.appContext && instance.vnode.appContext.provides : instance.parent.provides : currentApp._context.provides;
if (provides && key in provides) {
return provides[key];
} else if (arguments.length > 1) {
return treatDefaultAsFactory && isFunction(defaultValue) ? defaultValue.call(instance && instance.proxy) : defaultValue;
} else {
warn$1(`injection "${String(key)}" not found.`);
}
} else {
warn$1(`inject() can only be used inside setup() or functional components.`);
}
}
以上就是这俩歌api的源码部分。