Code前端首页关于Code前端联系我们

1.路由配置项写错,页面空白或跳转没反应

terry 2小时前 阅读数 8 #Vue

p>在Vue项目里,路由功能基本靠Vue Router来实现,但开发时稍不注意就会碰到各种路由错误,像页面突然空白、跳转没反应、刷新就白屏这些情况,特别影响开发效率,下面就把Vue Router开发中常见的错误场景一个个拆解,讲讲咋分析原因、咋解决~


路由配置是Vue Router的基础,可要是pathcomponent这些关键配置写错,页面要么空白,要么点了没反应。

常见错误点1:component拼写或引用错误

很多同学会把component写成components(多了个s),或者直接把组件名当字符串写,

// 错误写法:component写成components,或者组件没正确引入
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      components: Home // 这里多了s,而且Home没导入的话也会错
    }
  ]
})

正确做法是先导入组件(不管是静态导入还是懒加载),再把component值设为组件对象:

// 静态导入
import Home from '@/views/Home.vue'
// 懒加载
const About = () => import('@/views/About.vue')
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home // 注意是component单数
    },
    {
      path: '/about',
      component: About // 懒加载语法要对
    }
  ]
})

常见错误点2:路由顺序搞反,通配符没放最后

Vue Router是按路由配置顺序匹配的,要是把通配符(匹配404页面)放在前面,后面的路由就永远匹配不到了。

// 错误顺序:404路由在前面,导致/home也会匹配到*
const router = new VueRouter({
  routes: [
    { path: '*', component: Error404 },
    { path: '/home', component: Home }
  ]
})

得把通配符路由放到所有路由的最后,保证精确匹配的路由先生效:

const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/about', component: About },
    { path: '*', component: Error404 } // 最后放404
  ]
})

常见错误点3:path拼写错误或层级不对

比如想跳转到/user/profile,结果path写成/user/proflie(拼写错),或者嵌套路由里父路由path没写对,导致子路由匹配失败,这时候得逐行检查路由配置的path,可以结合Vue DevTools的“Routes”面板,看当前匹配的路由是否符合预期。

导航守卫逻辑乱,路由拦截失效或死循环

导航守卫(比如beforeEachbeforeRouteEnter)用来控制路由权限、页面跳转逻辑,但逻辑写不对就会出问题。

错误场景1:next()没调用或调用多次

全局前置守卫beforeEach里,必须确保每个分支都调用next(),否则路由会卡在半路上,比如权限判断时漏掉else分支:

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    if (isLogin()) {
      next() // 登录了放行
    } else {
      next('/login') // 没登录跳登录
    }
  }
  // 这里漏掉:如果路由不需要权限,也要调用next()
})

正确写法是覆盖所有情况,比如加个else或者在最后调用next()

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth) {
    if (isLogin()) {
      next()
    } else {
      next('/login')
    }
  } else {
    next() // 不需要权限的路由直接放行
  }
})

next()不能调用多次,比如在异步操作里重复调用:

router.beforeEach((to, from, next) => {
  axios.get('/api/checkAuth').then(res => {
    next() // 第一次调用
  })
  next() // 第二次调用,会报错
})

要把异步里的next()逻辑理顺,用async/await或者Promise控制流程。

错误场景2:全局守卫和组件内守卫冲突

比如全局beforeEach里做了权限拦截,组件内beforeRouteEnter又做了重复判断,导致逻辑混乱,这时候要理清守卫的执行顺序(全局前置→路由独享→组件内beforeRouteEnter),把权限逻辑集中在全局守卫,组件内守卫处理组件级的逻辑(比如表单未保存阻止跳转)。

动态路由匹配时,页面不更新或参数拿错

动态路由(如/user/:id)能根据不同参数渲染同一组件,但组件复用会导致生命周期不触发,参数也可能拿错。

问题表现:

/user/1跳转到/user/2,页面数据没变化,因为组件实例被复用了,created这些钩子不会重新执行。

解决方法1:用watch监听$route变化

在组件里监听$route,参数变化时更新数据:

export default {
  data() {
    return {
      userId: ''
    }
  },
  watch: {
    '$route'(to, from) {
      this.userId = to.params.id // 当id变化时更新
      this.fetchUser() // 重新请求数据
    }
  },
  mounted() {
    this.fetchUser()
  },
  methods: {
    fetchUser() {
      // 根据this.userId请求数据
    }
  }
}

解决方法2:用组件内守卫beforeRouteUpdate

这个守卫在路由参数变化但组件复用时触发:

export default {
  beforeRouteUpdate(to, from, next) {
    this.userId = to.params.id
    this.fetchUser()
    next() // 记得调用next()放行
  }
}

路由模式不兼容,部署后刷新白屏或404

Vue Router有hashhistory两种模式,配置不对在生产环境容易出问题。

场景1:history模式下,刷新页面报404

history模式靠HTML5的history.pushState实现,部署到服务器后,刷新页面时服务器会直接请求/user/1这样的路径,但服务器没对应的资源,就返回404。

解决方法是让服务器把所有路由请求转发到index.html,比如用Nginx配置:

location / {
  try_files $uri $uri/ /index.html;
}

这样不管请求哪个路径,都会回到Vue的入口文件,由前端路由处理。

场景2:hash模式下,锚点被手动修改导致路由错乱

hash模式的URL长这样:http://xxx.com/#/home,如果用户手动把后面的内容改掉(比如改成#/hom),路由就会匹配错误,所以要避免用户手动修改锚点,所有路由跳转都用router.pushrouter.replace等方法,不要手动改window.location.hash

路由懒加载失败,打包或加载报错

路由懒加载能减小首屏体积,但配置不对会导致chunk加载失败。

错误点1:webpack或babel配置不对

如果用Vue CLI创建的项目,默认支持懒加载,但如果自己配webpack,要确保babel-loader处理了懒加载的文件,并且开启了代码分割,比如webpack配置里要有:

module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  }
}

Babel要配置@babel/plugin-syntax-dynamic-import来支持() => import()语法。

错误点2:懒加载语法写错

正确的懒加载是const Home = () => import('@/views/Home.vue'),要是写成const Home = import('@/views/Home.vue')(少了箭头函数),就会变成静态导入,还可能报错。

错误点3:网络问题导致chunk加载失败

用户网络差时,懒加载的chunk可能加载失败,可以给Vue Router加错误处理:

const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
  return originalPush.call(this, location).catch(err => err)
}

或者在路由组件里用errorCaptured处理加载错误。

嵌套路由配置错,子路由不渲染

嵌套路由需要父组件里有<router-view>,否则子路由组件没地方渲染。

错误案例:

父路由配置了children,但父组件Home.vue里没写<router-view>

// 路由配置
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home,
      children: [
        { path: 'news', component: News }
      ]
    }
  ]
})
// Home.vue(错误,没<router-view>)
<template>
  <div>
    <h1>Home页面</h1>
  </div>
</template>

这时候访问/home/news,News组件不会渲染。解决方法是在父组件加<router-view>

<template>
  <div>
    <h1>Home页面</h1>
    <router-view></router-view> <!-- 子路由渲染的地方 -->
  </div>
</template>

子路由的path不要加斜杠,比如children里写path: '/news'会变成根路径下的/news,而不是/home/news,要改成path: 'news'(继承父路由的path)。

路由名称或路径重复,跳转混乱

路由的name和同层级的path必须唯一,否则会冲突。

场景1:name重复导致命名路由跳转错误

比如两个路由都叫'user'

const router = new VueRouter({
  routes: [
    { path: '/user', name: 'user', component: UserList },
    { path: '/user/:id', name: 'user', component: UserDetail } // 重复name
  ]
})

router.push({ name: 'user' })时,不知道该跳哪个,要给每个路由唯一的name,比如改成'userList''userDetail'

场景2:同层级path重复

在同一父路由的children里,path不能重复(动态路由除外,比如/user/:id/user/:name算不同路由,但实际开发少这么用),要确保每个路由的path在同层级唯一。

404页面不显示或重定向循环

404页面靠通配符实现,但配置不对就不显示;重定向写循环会导致页面无限跳转。

404配置错误:

通配符路由没放最后,导致被前面的路由拦截。

const router = new VueRouter({
  routes: [
    { path: '*', component: Error404 },
    { path: '/home', component: Home }
  ]
})

访问/home时,先匹配到,所以永远到不了Home页面,要把路由放最后。

重定向循环:

比如A重定向到B,B又重定向到A:

const router = new VueRouter({
  routes: [
    { path: '/a', redirect: '/b' },
    { path: '/b', redirect: '/a' }
  ]
})

这会导致无限重定向,浏览器报错,要检查重定向链条,确保是单向的,比如/a/b/c这种线性结构。

路由传参丢失或解析错

paramsquery传参时,稍不注意参数就丢了或解析错。

params传参刷新丢失

params是基于路由配置的动态段(如/user/:id),如果路由没配置动态段,用params传参,刷新后参数会丢失。

// 路由没配:id
{ path: '/user', component: User }
// 传参
router.push({ name: 'user', params: { id: 1 } })

刷新后$route.params.id就没了。解决方法:要么把path改成/user/:id(动态路由),要么用query传参(query参数在URL里,刷新不丢),或者把params存到sessionStorage里。

query传参格式错误

如果传对象给query

router.push({
  path: '/search',
  query: { keywords: { name: 'vue', type: 'framework' } }
})

URL会变成/search?keywords=[object%20Object],解析时出错,要把对象转成字符串,比如用JSON.stringify

router.push({
  path: '/search',
  query: { 
    keywords: JSON.stringify({ name: 'vue', type: 'framework' }) 
  }
})
// 接收时解析
const keywords = JSON.parse(this.$route.query.keywords)

传参时拼写错误

比如想传userId,结果写成userID(大小写错),或者路由里的path/profile,跳转时写成/proflie(拼写错),要仔细检查参数名和路由路径的拼写。

上面这些就是Vue Router开发中常见的错误和解决办法啦~其实很多错误都是配置细节、逻辑顺序或者语法的小问题,开发时多结合Vue DevTools看路由状态,控制台看报错信息,再对照路由配置一步步排查,基本都能解决~要是碰到没见过的错误,也可以去Vue Router官方文档翻一翻,里面对每个API和配置的说明都很详细,能帮你理清逻辑~

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门