当使用在中间件内使用
useRoute
的可组合项时,我收到此警告:“[nuxt] 在中间件内调用 useRoute 可能会导致误导结果。相反,使用传递给中间件的 (to, from) 参数来访问新路由和旧路由。'
我尝试了这里的解决方案:https://github.com/nuxt-modules/i18n/issues/2064和这里Nuxt i18n 在中间件中调用 useRoute 可能会导致误导性结果,但它们不适用于我。我试图了解这是否是一个需要等待修复的错误,或者是否有实际的解决方案。我在
useRoute
内部使用 useStoreAuth()
,但不在 checkSession
内部使用。由于我在中间件中添加了useStoreAuth
,所以它说我无法使用useRoute
。为使用 signIn
的 useRoute
函数创建单独的可组合项将不起作用,因为我需要在 signedIn
和 useStoreAuth
函数中访问来自 checkSession
的 signIn
引用。此外,我需要在 checkSession
中使用 signIn
,这意味着如果我创建一个名为 useStoreSession
的单独可组合项并将其添加到中间件,它还将包含 useStoreAuth
和 useRoute
。
export default defineNuxtRouteMiddleware(async (to, _from) => {
const { signedIn, checkSession } = useStoreAuth();
await checkSession();
if (!signedIn.value && to.path.startsWith('/profile')) {
return navigateTo(`/sign-in?redirect=${encodeURIComponent(to.path)}`);
}
if (signedIn.value && to.path === '/sign-in') {
return navigateTo('/');
}
});
我在可组合项中使用
useRoute
的方式:
export const useStoreAuth = () => {
const route = useRoute();
const signIn = async (signInData: SignInData) => {
const { apiBase } = useRuntimeConfig().public;
state.pending = true;
state.error = null;
state.successMessage = null;
const res = await fetch(`${apiBase}/signIn`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(signInData),
});
try {
if (res.ok) {
await checkSession();
if (state.signedIn) {
if (route.query.redirect) {
await navigateTo(`${route.query.redirect}`);
} else {
await navigateTo(`${route.query.redirect}` || '/');
}
state.successMessage = 'Signed in successfully';
} else {
state.error = 'Error signing in';
}
} else if (res.status === 400) {
state.error = 'Validation error';
} else {
const resData = await res.json();
state.error = resData.message || "User doesn't exist";
}
} catch (err) {
state.error = `An unexpected error occurred ${err.message}`;
} finally {
state.pending = false;
}
};
return {
...toRefs(state),
signIn,
};
};
寻找可能的解决方案。
为了在 Pinia 存储中可靠地使用可组合项,应保证在允许组合项时进行初始化,即第一个
useStore()
调用应在组件的设置中发生,而不是更早。如果 store 用于其他地方(例如路由器钩子),则这是不可行的,第一次导航可以在创建组件实例之前发生在 Vue 中。
更实用的方法是在可组合项可访问时注入具有可组合结果的商店,例如在根组件中:
store.route = useRoute()
在这种情况下,这就是解决方案,因为路由器挂钩中仅使用
checkSession
。只要不使用route
,此时后者是否未初始化也没关系。如果在此之前使用 route
,这将是一个问题,可能的解决方法是允许使用它的方法 (signIn
) 选择性地通过参数接受路由对象。所以它可以用作路由器钩子中的store.signIn(data, to)
,而signIn
可以用作(route.value ?? routeArg).query.redirect
。再说一次,这不是问题,但如果是的话,这就是解决问题的方法。
这也表明可能存在设计问题,存储包含可能属于路由器的路由逻辑。在这种情况下,
sign-in
路由和路由器钩子可以处理redirect
参数和可能的重定向,并且根组件可以对store.signedIn
状态的变化做出反应,而存储将负责不依赖于特定的逻辑。路线实施。