Vue.js项目store与router引入触发import/no-cycle依赖循环报错如何解决
问题根源
你当前的依赖形成了闭环,所以触发import/no-cycle报错:router/index.js → 引入store/index.js → 引入store/modules/common.js → 引入router/index.js
同时你的代码本身存在两处语法/规则错误,也是功能异常的原因:
- 路由独享守卫
beforeEnter的this指向为undefined,根本无法通过this.$store读取状态 beforeRouteLeave是组件内守卫,写在路由配置中不会生效,需要移到对应页面组件内部
解决方案
步骤1:调整路由守卫逻辑,无需顶部引入store
修改router/index.js代码如下,直接从Vue原型读取已经挂载的$store,避免引入store触发循环:
import Vue from 'vue'; import VueRouter from 'vue-router'; import Home from '../views/Home.vue'; Vue.use(VueRouter); const routes = [ { path: '/data', name: 'Data', component: () => import('../views/Data.vue'), beforeEnter: (to, from, next) => { // 直接读取Vue原型上挂载的store,不需要顶部引入 if (Vue.prototype.$store.state.common.loginFlag === false) { next('/login'); } else { next(); } }, }, ]; const router = new VueRouter({ routes, }); export default router;
步骤2:移除store中的router引入,将跳转逻辑移到调用层
Vuex的核心职责是管理全局状态,不应该处理路由跳转这类视图层逻辑,从根源切断循环依赖。
修改store/modules/common.js代码如下:
import Vue from 'vue'; import Vuex from 'vuex'; import axios from 'axios'; // 移除顶部的router引入 Vue.use(Vuex); const data = { userNotFound: false, passwordNoMatch: false, loginFlag: false, }; const getters = { userNotFound: (state) => state.userNotFound, passwordNoMatch: (state) => state.passwordNoMatch, loginFlag: (state) => state.loginFlag, }; const actions = { // 返回请求的promise,方便调用层拿到登录结果 login: ({ commit }, { payload }) => { const path = 'http://localhost:5000/login'; return axios.post(path, payload) .then((res) => { commit('setNoPasswordMatch', res.data.Password_no_match); commit('setUserNotFound', res.data.Not_found); if (res.data.login_flag) { commit('session/setUserObject', res.data.user, { root: true }); commit('setLoginFlag', res.data.login_flag); return { success: true } } return { success: false } }) .catch((error) => { console.log(error); return { success: false } }); }, }; // 补全缺失的mutation,否则状态不会更新 const mutations = { setNoPasswordMatch(state, val) { state.passwordNoMatch = val }, setUserNotFound(state, val) { state.userNotFound = val }, setLoginFlag(state, val) { state.loginFlag = val } }; export default { namespaced: true, state: data, getters, actions, mutations, };
在你调用登录接口的页面组件(一般是登录页)中处理路由跳转:
// 登录页表单提交方法示例 async handleLogin() { const res = await this.$store.dispatch('common/login', { payload: this.loginForm }) if (res.success) { // 组件内可直接获取$router执行跳转 this.$router.push({ name: 'Data' }) } else { // 自行处理登录失败提示 alert('登录失败') } }
步骤3:确认main.js的注册顺序
确保main.js中先注册store,再注册router,保证路由守卫执行前$store已经挂载到Vue原型:
import Vue from 'vue' import App from './App.vue' import store from './store' // store引入必须在router之前 import router from './router' new Vue({ store, router, render: h => h(App) }).$mount('#app')
调整完成后依赖循环会完全切断,lint报错自动消失,状态读取、路由跳转功能也会恢复正常。
内容的提问来源于stack exchange,提问作者ravenUSMC
相关产品推荐
相关产品推荐

