Vue2升级Vue3后vue-router报Uncaught TypeError问题求解
问题
将项目从Vue2升级至Vue3时遇到报错,控制台错误信息:
vue-router.mjs:3499 Uncaught TypeError: Cannot read properties of undefined (reading 'location')
对应报错代码行(位于node_modules/front/node_modules/vue-router/dist/vue-router.mjs):
push(routerHistory.location).catch(err => { if ((process.env.NODE_ENV !== 'production')) warn('Unexpected error when starting the router:', err); });
使用的vue-router版本为^4.1.2,附上相关代码:
main.js
import { library } from '@fortawesome/fontawesome-svg-core'; import {faSpinner} from '@fortawesome/free-solid-svg-icons'; import SortedTablePlugin from 'vue-sorted-table/src'; import { FontAwesomeIcon, FontAwesomeLayers } from '@fortawesome/vue-fontawesome'; import { BootstrapVue3 } from 'bootstrap-vue-3'; import { createApp, h } from 'vue'; import App from './App.vue'; import './registerServiceWorker'; import router from './router'; library.add( faSpinner, ); const app = createApp({ render: () => h(App), }); app.use(router); app.use(BootstrapVue3); app.use(SortedTablePlugin); app.component('font-awesome-icon', FontAwesomeIcon); app.component('font-awesome-layers', FontAwesomeLayers); app.mount('#app');
router/index.js
// import Vue from 'vue'; import { createRouter } from 'vue-router'; import FormStep from '@/components/FormStep.vue'; import DualTable from '@/components/DualTable.vue'; import ListTable from '@/components/ListTable.vue'; import CaptureScreen from '@/components/CaptureScreen.vue'; import StageScreen from '@/components/StageScreen.vue'; import TopScreenConfig from '@/components/TopScreenConfig.vue'; import EmailCapture from '@/components/EmailCapture.vue'; import store from '@/store'; // Vue.use(VueRouter); const routes = [ { path: '/form/:form/step-:step', name: 'FormStep', component: FormStep, }, { path: '/form/:form/step-:step/:related', component: FormStep, }, { path: '', name: 'ListTable', component: ListTable, }, { path: '/:status.html', component: ListTable, }, { path: '/personal/', component: ListTable, }, { path: '/personal/:status.html', component: ListTable, }, { path: '/aggregator/', component: ListTable, }, { path: '/aggregator/:status.html', component: ListTable, }, { path: '/config/case_and_process_types.html', component: DualTable, }, { path: '/run_stage/:id/', name: 'StageScreen', component: StageScreen, }, { path: '/capture/:id/', name: 'CaptureScreen', component: CaptureScreen, }, { path: '/capture_from_email/:email/:id/', name: 'EmailCaptureScreen', component: EmailCapture, }, { path: '/config/screens/:id.html', name: 'ScreenConfig', component: TopScreenConfig, }, { path: '/config/:model/', name: 'ConfigList', component: ListTable, }, { path: '/emails/', name: 'Emails', component: ListTable, }, ]; const router = createRouter({ mode: 'history', base: process.env.BASE_URL, routes, }); router.beforeEach((to, from, next) => { if (to.matched.some((record) => record.meta.requiresAuth) && !store.state.user.isAuthenticated) { next('/login/'); return; } next(); }); export default router;
疑问:该错误是否与注释掉的Vue.use(VueRouter)有关?该如何修复?
解决方案
关于Vue.use(VueRouter)的疑问
注释掉Vue.use(VueRouter)和当前报错无关。Vue3中使用createRouter创建路由实例,不再需要通过Vue.use()注册插件,这部分是正确的升级操作。
报错原因及修复方法
这个报错的核心原因是Vue Router 4.x 不再使用mode选项配置路由模式,你在createRouter里写的mode: 'history'是Vue2的写法,Vue3中需要通过导入并使用对应的history模式对象来配置:
- 在
router/index.js中导入createWebHistory:
import { createRouter, createWebHistory } from 'vue-router';
- 修改
createRouter的配置,把mode: 'history'替换成history: createWebHistory(process.env.BASE_URL):
const router = createRouter({ history: createWebHistory(process.env.BASE_URL), routes, });
修改后,路由实例就能正确初始化routerHistory对象,解决location读取失败的报错。
额外检查点
- 执行
npm list vue-router确认项目中没有同时安装Vue Router 3.x和4.x版本,若有冲突则卸载旧版本:npm uninstall vue-router@3 - 检查所有路由导航的调用方式是否适配Vue3,比如在setup语法中需要用
useRouter()钩子获取路由实例,替代Vue2中的this.$router
内容的提问来源于stack exchange,提问作者edche
相关产品推荐
相关产品推荐

