vue2 router 执行 next() 为什么没有进页面?

路由拦截部分代码如下:

export default (to, from, next,router) => {

  console.log('beforeEach-----------------------------begin-----------------------------to.path')
  console.log('to.path:'+to.path)

  // 如果路由为空,添加路由
  if(router.getRoutes().length===0) {
    router.addRoutes(store.getters['router/staticRoutes'])
  }

  // 白名单页面路由
  // let whiteList=["/login","/404","/home","/testo","/testt","/testt/tests",'/testo/testw','/']
  let whiteList=["/login","/404"]
  // token
  let token=localStorage.getItem('token')
  // 动态路由表
  let routes=store.state.router.menu

  // 没有token && 目标路由在白名单
  if(!token && whiteList.includes(to.path)){
    console.log('beforeEach--------------------------next_2')
    next()
  }

  // 没有token && 目标路由不在白名单
  if(!token && !whiteList.includes(to.path)){
    console.log('beforeEach--------------------------next_3')
    console.log(`next_path--------------------------/login?redirect=${to.path}`)
    next(`/login?redirect=${to.path}`)
  }

  // 有token && 目标路由是登录页
  if(token && to.path=='/login'){
    console.log('beforeEach--------------------------next_4')
    console.log(`next_path--------------------------path: '/home'`)
    next({ path: '/home' })
  }

  // 有token && 目标路由不是登录页 && 已经有路由表hasRoles
  if(token && to.path!='/login' && routes.length!==0){
    console.log('beforeEach--------------------------next_5')
    next()
  }

  // 有token && 目标路由不是登录页 && 没有路由表hasRoles
  if(token && to.path!='/login' && routes.length==0 ){

    store.dispatch('router/getRoutes').then(res=>{

      // 路由数据存到 store 里面了,添加一次路由然后跳转
      router.addRoutes(store.getters['router/staticRoutes'])
        console.log('beforeEach--------------------------next_6')
        console.log(`next_path--------------------------/login?redirect=${to.path}`)
        next(`/login?redirect=${to.path}`)
    })
  }

}

没登陆之前直接输入地址:
http://localhost:8081/
或者
http://localhost:8081
都会跳转到:
http://localhost:8081/login?redirect=%2F
页面也会正常显示:
image.png
或者在地址栏直接输入主页面地址:
http://localhost:8081/home
也会判断有没有登录然后重定向回登录页:
image.png
这里的 redirect 参数本意是要留到登陆页面后面登陆成功后就直接跳转到用户的目标页面用的,
但我直接输入登录页地址:
http://localhost:8081/login
next()也执行了,但是并没有进入登录页,也没有报错:
image.png
我的路由配置是写在 store 中,通过路由拦截动态添加的,具体如下:


import Layout from "@/layout/index.vue";
import {  getRoutesAPI } from "@/api/userApi";
const state = {
  // 静态路由
  staticMenu:[
    // 访问根路径切换回到home
    {
      path: '/',
      component: Layout,
      redirect: '/home',
    },

    // 登录页
    {
      path: '/login',
      component: () =>
        import('@/views/login/index'),
      hidden: true
    },

    //   找不到页面
    {
      path: '/404',
      component: () =>
        import('@/views/errorPage/404'),
      hidden: true
    },

    // 匹配不到的页面全部跳转到404
    {
      path: '*',
      redirect: '/404', // 将所有未匹配到的路由重定向到404路由
      hidden: true
    },

  ],
  
  menu:[],

}

const getters={
  staticRoutes(state){
    return state.staticMenu.map(item=>{
      if(item.path=='/'){
        item.children=state.menu
      }
      return item
    })
  },
}

const mutations = {
  SET_MENU: (state, menu) => {
    state.menu=routeFormat(menu)
  },
}

const actions = {
  // 获取动态路由
  getRoutes({ commit }){
    return getRoutesAPI().then((ref)=>{
      commit('SET_MENU',ref.data)
      return (ref)
    }).catch(e=>e)
  }
}

// 路由表格式化
function routeFormat(routeList){
  return routeList.map(item=>{
    let timeObj= JSON.parse(JSON.stringify(item))
    timeObj.component = () => import('@/views'+item.component)
    timeObj.meta=JSON.parse(item.meta)
    if(item.ChildList){
      timeObj.ChildList=routeFormat(item.ChildList)
    }
    return timeObj
  })
}

export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}

但是我个人觉得这个应该和路由配置没有关系,因为之前是能进去的,和登录页面应该也没有关系,前面那一串 ?????是 登录页面中的

  beforeMount() {
    console.log("?????????????????")
  },

所以这个空白页应该也不是登录页组件里面的问题,但是又想不到还能是哪里的问题,接下来应该从哪里着手排查?
----------------------------------------ps 补充解释------------------------------------------

把路由守卫所有判断逻辑都删掉,简化成如下代码后依然是不能直接访问:

//路由创建脚本
import Vue from 'vue'
import Router from 'vue-router'
import beforeEachCallback from './beforeEach'

Vue.use(Router)

const createRouter = () => new Router({
  scrollBehavior: () => ({ y: 0 }),
  base:'/',
  mode:"history",
})
const router = createRouter()

router.beforeEach((to, from, next)=>{beforeEachCallback(to, from, next,router)})

export default router

//路由守卫回调
import store from '@/store'
export default (to, from, next,router) => {

  console.log('beforeEach-----------------------------begin-----------------------------to.path')
  console.log('to.path:'+to.path)

  // 如果路由为空,添加路由
  if(router.getRoutes().length===0) {
    router.addRoutes(store.getters['router/staticRoutes'])
  }

  next()

}

现在守卫已经直接放行了,依然进不去,所以应该不是路由守卫里的逻辑问题。

前面路由守卫贴出详细代码主要是为了说明虽然直接写 url 进不去,但是通过判断跳转后尽然还能跳转进去,所以路由配置应该也没问题吧。。。。

阅读 277
2 个回答

建议使用debug排查,应该很快就会解决

image.png

或者使用vscode直接debug调试,内部的运行流程很快就整明白,vscode调试不清楚的可以 看下这篇文章 vscode调试

路由守卫逻辑问题,建议重构一下路由

// router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import beforeEachCallback from './beforeEach'
import store from '@/store'

Vue.use(Router)

const createRouter = () => new Router({
  scrollBehavior: () => ({ y: 0 }),
  base:'/',
  mode:"history",
  routes: store.getters['router/staticRoutes'] // 创建的时候就加静态路由
})

const router = createRouter()

router.beforeEach((to, from, next) => {
  console.log('beforeEach-----------------------------begin-----------------------------to.path')
  console.log('to.path:'+to.path)

  // 白名单路由
  let whiteList=["/login","/404"]
  let token = localStorage.getItem('token')

  if (!token && whiteList.includes(to.path)) {
    return next()
  }

  if (!token && !whiteList.includes(to.path)) {
    return next(`/login?redirect=${to.path}`)
  }

  if (token && to.path === '/login') {
    return next('/home')
  }

  if (token && !store.state.router.menu.length) {
    store.dispatch('router/getRoutes').then(() => {
      // 加动态路由之后要加上 replace: true
      next({ ...to, replace: true })
    })
  } else {
    next()
  }
})

export default router

在登录页里加生命周期钩子测试一下看看:

export default {
  name: 'Login',
  created() {
    console.log('Login component created');
  },
  mounted() {
    console.log('Login component mounted');
  },
  beforeDestroy() {
    console.log('Login component beforeDestroy');
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏