vue3+vue-router4:报错Uncaught (in promise) Error: Invalid navigation guard

7 篇文章 3 订阅
5 篇文章 0 订阅
报错图示:

Error: Invalid navigation guard
Uncaught (in promise) Error: Invalid navigation guard
在这里插入图片描述

错误影响描述:

配置开发、测试、生产时候,因为是公众号,所以想在开发环境下免鉴权,不走微信获取openid接口,pinia中定义好openid直接进入项目,遂遇此问题。
因为在async和await中使用,导致next()不能正确执行,查看源码,因为在非生产环境做了此限制,所以只要是生产环境就没问题,但是我就是要dev使用呀。

错误代码示例:
// vant4函数形式的组件
import '@/assets/js/vant4.js'
import '@/assets/css/main.css'
import { getQueryString } from '@/assets/js/common.js'
import { showToast } from 'vant'

import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router/index'
// pinia 共享仓库
import { createPinia ,storeToRefs } from "pinia";
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
// 接口
import { getWechatInfoByCode ,getByOpenid } from '@/api/index'
import { useStore } from '@/store/index'

const pinia = createPinia()
const app = createApp(App)
// 数据持久化
pinia.use(piniaPluginPersistedstate);
// 环境变量挂在全局
app.config.globalProperties.$getEnv = import.meta.env

app.use(pinia)
app.use(router)
app.mount('#app')


// 路由守卫 start
router.beforeEach( async (to, from, next) => {
    const store = useStore();
    // 必须storeToRefs绑定否则拿不到最新值
    const { openid } = storeToRefs(store);
    const { VITE_HOST , VITE_APPID } = import.meta.env
    // 微信公众号appid-开发-基本配置中获取
    const appId = VITE_APPID
    // 获取code后再次跳转路径 window.location.href;例:www.baido.com/#/Home
    const toPath = VITE_HOST + '/#' + to.path
    // 核心步骤,获取code
    const hrefurl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodeURIComponent(toPath) + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
    // 从地址栏获取code
    const code = getQueryString('code')
    // 有openid就放行,单纯为了获取openid,无需关心是否登录,绑定等
    const haveOpenidPass = ['/bindAccount' , '/register']
    // 是否账号绑定了openid  
    const isBindAccount = async () => {
        const resGetInfo = await getByOpenid({ openid: openid.value })
        if(resGetInfo.code === 0){
            if(resGetInfo.data){
                // 已绑定
                store.setLoginInfo(resGetInfo.data)
                // dev test 环境都会跳转失效并报错,生产可以正常跳转无报错 !!!
                next()
            }else{
                // 未绑定 
                // 清空store用户信息
                store.setLoginInfo({
                    user:{
                        Uid:''
                    }
                })
                // contactUs 相当于注册,直接通过
                if(to.path == '/contactUs'){
                	// dev test 环境都会跳转失效并报错,生产可以正常跳转无报错 !!!
                    next()
                }else{
                    next({
                        path: '/register'
                    })
                }         
            }
        }else{
            // 请求失败,放行
            showToast(resGetInfo?.info || '请求失败!');
            next()
        }
    }

    /* 路由发生变化修改页面title */
    if (to.meta.title) {
        document.title = to.meta.title;
    }
    /* 判断该路由是否需要登录权限 */
    if (to.matched.some(record => record.meta.requireAuth)) {
        if (openid.value) {
            if(haveOpenidPass.includes(to.path)){
                next()
            }else{
            	// !!!错误的根源在此 !!!
                isBindAccount()
            } 
        } else { //openId不存在
            if (code) { //根据code获取openId
                const res = await getWechatInfoByCode({ code })
                if (res && res.code == 0) {
                    store.setOpenid(res.data.openid)
                    isBindAccount()
                } else {
                    showToast(res?.info || '请求失败!');
                }
            } else {  //获取code
                window.location.replace(hrefurl)
            }
        }
    } else {
        next()
    }
})
// 路由守卫 end

解决方式:

只需要给isBindAccount()函数调用时候加个return就行。

// vant4函数形式的组件
import '@/assets/js/vant4.js'
import '@/assets/css/main.css'
import { getQueryString } from '@/assets/js/common.js'
import { showToast } from 'vant'

import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router/index'
// pinia 共享仓库
import { createPinia ,storeToRefs } from "pinia";
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
// 接口
import { getWechatInfoByCode ,getByOpenid } from '@/api/index'
import { useStore } from '@/store/index'

const pinia = createPinia()
const app = createApp(App)
// 数据持久化
pinia.use(piniaPluginPersistedstate);
// 环境变量挂在全局
app.config.globalProperties.$getEnv = import.meta.env

app.use(pinia)
app.use(router)
app.mount('#app')


// 路由守卫 start
router.beforeEach( async (to, from, next) => {
    const store = useStore();
    // 必须storeToRefs绑定否则拿不到最新值
    const { openid } = storeToRefs(store);
    const { VITE_HOST , VITE_APPID } = import.meta.env
    // 微信公众号appid-开发-基本配置中获取
    const appId = VITE_APPID
    // 获取code后再次跳转路径 window.location.href;例:www.baido.com/#/Home
    const toPath = VITE_HOST + '/#' + to.path
    // 核心步骤,获取code
    const hrefurl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodeURIComponent(toPath) + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
    // 从地址栏获取code
    const code = getQueryString('code')
    // 有openid就放行,单纯为了获取openid,无需关心是否登录,绑定等
    const haveOpenidPass = ['/bindAccount' , '/register']
    // 是否账号绑定了openid  
    const isBindAccount = async () => {
        const resGetInfo = await getByOpenid({ openid: openid.value })
        if(resGetInfo.code === 0){
            if(resGetInfo.data){
                // 已绑定
                store.setLoginInfo(resGetInfo.data)
                next()
            }else{
                // 未绑定 
                // 清空store用户信息
                store.setLoginInfo({
                    user:{
                        Uid:''
                    }
                })
                // contactUs 相当于注册,直接通过
                if(to.path == '/contactUs'){
                    next()
                }else{
                    next({
                        path: '/register'
                    })
                }         
            }
        }else{
            // 请求失败,放行
            showToast(resGetInfo?.info || '请求失败!');
            next()
        }
    }

    /* 路由发生变化修改页面title */
    if (to.meta.title) {
        document.title = to.meta.title;
    }
    /* 判断该路由是否需要登录权限 */
    if (to.matched.some(record => record.meta.requireAuth)) {
        if (openid.value) {
            if(haveOpenidPass.includes(to.path)){
                next()
            }else{
                // 处理非prod环境下,控制台异常,报错无法跳转问题
                return isBindAccount()
            } 
        } else { //openId不存在
            if (code) { //根据code获取openId
                const res = await getWechatInfoByCode({ code })
                if (res && res.code == 0) {
                    store.setOpenid(res.data.openid)
                    isBindAccount()
                } else {
                    showToast(res?.info || '请求失败!');
                }
            } else {  //获取code
                window.location.replace(hrefurl)
            }
        }
    } else {
        next()
    }
})
// 路由守卫 end

备注:

vue3的ref变量使用必须加.value,卧槽,反人类啊,开倒车!!!经常忘记,导致我疯狂debug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘斩仙的笔记本

富贵险中求

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值