Skip to content

Redirected when going from "/login" to "/dashboard" via a navigation guard. #3945

Description

@xyy010890

当运行以下代码时,页面报错如图,求大佬告知这是啥情况

Image

报错内容:

Uncaught runtime errors:
×
ERROR
Redirected when going from "/login" to "/dashboard" via a navigation guard.
at createRouterError (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1731:15)
at createNavigationRedirectedError (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:1716:10)
at eval (webpack-internal:///./node_modules/vue-router/dist/vue-router.esm.js:2015:17)
at eval (webpack-internal:///./src/router/index.js:80:7)


"vue-router": "^3.6.5",

// 导入 Vue 和 VueRouter 核心库
import Vue from "vue";
import VueRouter from "vue-router"

// 导入静态路由表(例如登录页、404 等所有用户都可以访问的页面)
import staticRoutes from "@/router/modules/staticRoutes";

// 导入 Vuex store 实例,用于访问全局状态
import store from "@/store";
//
// // 导入一个异步函数,它根据后端返回的菜单列表生成动态路由配置
import {dynamicRoutesAsync} from "@/router/modules/dynamicRoutes";

// 告诉 Vue 使用 VueRouter 插件
Vue.use(VueRouter);

// 初始化路由表:将静态路由展开放入 routes 数组
const routes = [
    ...staticRoutes,   // 展开运算符,将 staticRoutes 中的每个路由对象加入数组
];

// 定义白名单:这些路径不需要登录验证,可以直接访问
const whiteList = ['/login', '/register', '/404', '/auth-redirect', "/500"];

// 创建 VueRouter 实例,使用 history 模式(去掉了 URL 中的 #
const Router = new VueRouter({
    mode: "history",   // 使用 HTML5 History 模式
    routes,            // 传入初始路由表(只包含静态路由)
});

// 定义一个标志,记录动态路由是否已经添加到路由器中
// 用于避免重复添加动态路由,提高性能并防止路由重复定义错误
Router.beforeEach(async (to, from, next) => {
        console.log("进入路由")
        // 如果路径在白名单内,直接继续,并且后续代码不执行
        if (whiteList.includes(to.path)) {
            console.log(to.path)
            next()
            return
        }
        // 如果vuex没有用户信息,则获取用户信息
        if (!store.state.user.userProfile?.id) {
            console.log("获取用户信息")
            const result = await store.dispatch("user/userProfile");
            if (!result.success) {
                console.warn("获取用户信息失败", result.message);
                next("/login");
                return;
            }
        }
        if (!store.state.app.dynamicRoutesAdded) {
            try {
                console.log("进入加载动态路由")
                // 调用菜单模块的 fetchMenus action,从后端获取当前用户的菜单列表
                await store.dispatch("menus/fetchMenus");
                // 从 Vuex 中取出菜单列表
                const menuList = store.state.menus.menusList;
                // 调用动态路由生成函数,传入菜单列表和视图组件所在的目录名(这里是 "views")
                // 该函数会返回一个路由配置数组
                const asyncRoutes = await dynamicRoutesAsync(menuList, "views");

                // 遍历生成的动态路由数组,逐个添加到 Router 实例中
                asyncRoutes.forEach(route => {
                    Router.addRoute(route);   // addRoute 是 VueRouter 的动态添加路由方法
                });
                // 设置标志,表示动态路由已经添加完成
                store.commit("app/SET_DYNAMIC_ROUTES_ADDED", true)
                next({path:to.path,replace:true})
                return
            } catch (error) {
                console.warn("路径加载失败", error)
                next("/500")
                return
            }
        }
        next()
    }
)

// 导出配置好的 Router 实例,供 main.js 使用
export default Router;
---------------------
<script>

import {mapActions} from "vuex";

export default {
  name: "Login",
  data() {
    return {
      username: "",
      password: ""
    }
  },
  methods: {
    ...mapActions("user", ["login"]),
    handleInput() {
      const illegalChars = [
        // 空白字符
        ' ', '\t', '\n', '\r', '\f', '\v',
        // 常见特殊符号
        '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',',
        '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^',
        '`', '{', '|', '}', '~',
        // 其他可能禁止的符号(如中文全角符号可根据需要添加)
        '', '', '', '', '', '', '', '', '', '', '', '', '', ''
      ];
      const escaped = illegalChars.map(c => c.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('');
      const regex = new RegExp(`[${escaped}]`, 'g');

      // 过滤输入值并更新数据
      this.username = event.target.value.replace(regex, '');
    },
    async handleLogin() {
      const res = await this.login({username: this.username, password: this.password})
      if (res.success) {
        alert(res.message)
        this.$router.push("/dashboard")
      } else {
        alert(res.message)
      }
    }
  },
}
</script>

<template>
  <div class="Login-Page">
    <div class="Login-Container">
      <div class="form-group">
        <label for="InputUsername">用户名</label>
        <input type="text"
               class="form-control"
               id="InputUsername"
               aria-describedby="UsernameHelp"
               placeholder="请输入用户名"
               v-model="username"
               @input="handleInput">
        <small id="UsernameHelp" class="form-text text-muted">请输入用户名或者邮箱</small>
      </div>
      <div class="form-group">
        <label for="InputPassword">密码</label>
        <input type="password"
               class="form-control"
               id="InputPassword"
               v-model="password">
      </div>
      <div class="form-group form-check">
        <input type="checkbox" class="form-check-input" id="RememberMe">
        <label class="form-check-label" for="eRememberMe">记住密码</label>
      </div>
      <button type="submit"
              class="btn btn-primary"
              @click="handleLogin">登录
      </button>
    </div>
  </div>
</template>

<style scoped>
.Login-Page {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  width: 100%;
  min-height: 100vh;
}

.Login-Container {
  width: 30%;
  height: auto;
  padding: 20px;
  border-radius: 20px;
  box-shadow: 20px 20px 20px 10px #bdd7b6;
}
</style>
-------------------------------------------

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions