【问题标题】:How to access this variable from my store / state in my vue router?如何从我的 vue 路由器中的商店/状态访问此变量?
【发布时间】:2019-03-21 11:01:37
【问题描述】:

我已经设置了我的 routes.js 文件以从我的商店导入我的状态。这就像我 console.log(state) 它成功地将我的商店输出到控制台一样工作:

然后我将我的路线定义如下:

routes.js

   
import { state } from './store/store';
// import { mapState, mapGetters } from "vuex";

console.log(state)

const routes = [
{
  path: '/',
  name: 'home',
  component: Home
},
{
  path: '/dashboard',
  name: 'dashboard',
  component: Dashboard,
},
{
  path: '/project/:id',
  name: 'project',
  component: Project,
  props: true,
  meta: {
    requiresAuth: true,
  },

  children: [
        {
          path: 'module/:module',
          name: 'module',
          component: Tasks,
          props: true,

          children: [
                  {
                    path: 'task/:url',
                    name: 'task',
                    component:  () => import(`./components/ProductServiceAnalysis/${$state.taskURL}.vue`),
                    props: true,

我收到错误: app.js:59653 [vue-router] Failed to resolve async component default: ReferenceError: state is not defined 与我尝试访问 state.taskURL 变量的倒数第二行有关。

为什么会出错?以及如何从路由器访问商店中的 taskURL 变量?

如果我处理不正确,请提供建议。

这是我的 store.js:

import Vue from 'vue';
import Vuex from 'vuex';
import axios from 'axios'

Vue.use(Vuex);
axios.defaults.baseURL = 'http://buildmybusiness.test/api'

Vue.config.devtools = true;

export const state = {
	token: localStorage.getItem('access_token') || null,
	requiredTask: 'This is my current task',
	currentModule: '1',
	currentModuleName: 'Product & Service Analysis',
	currentTask: '1',
	modules:[],
	tasks:[],
	taskName:[],
	actions:[],
	userId: localStorage.getItem('loggedin_user') || null,
	userName: localStorage.getItem('loggedin_username') || null,
	projects:[],
	currentProjectId: '',
	currentProjectName: '',
	taskURL: 'define-product-service'
}

export const store = new Vuex.Store({

	state,

	mutations: {
		SET_MODULES: (state, payload) => {
			state.modules = payload;
		},

		SET_TASKS: (state, tasks) => {
			state.tasks = tasks;
		},

		SET_MODULE_TITLE: (state, moduleTitle) => {
			state.currentModuleName = moduleTitle
		},

		SET_ACTIONS: (state, payload) => {
			state.actions = payload;
		},

		RETRIEVE_TOKEN: (state, token) => {
			state.token = token;
		},
		DESTROY_TOKEN: (state) => {
			state.token = null;
		},
		SET_USERID: (state, userid) => {
			state.userId = userid;
		},
		DESTROY_USERID: (state) => {
			state.userId = null;
		},


		SET_USERNAME: (state, username) => {
			state.userName = username;
		},
		DESTROY_USERNAME: (state) => {
			state.userName = '';
		},


		SET_PROJECTS: (state, projects) => {
			state.projects = projects;
		},
		DESTROY_PROJECTS: (state) => {
			state.projects = [];
		},


		SET_PROJECT_ID: (state, projectId) => {
			state.currentProjectId = projectId;
		},
		SET_PROJECT_NAME: (state, projectName) => {
			state.currentProjectName = projectName;
		},


		SET_ACTION_URL: (state, taskURL) => {
			state.taskURL = taskURL;
		},

	},

	getters: {

		loggedIn(state){
			return state.token !== null;
		},

		SelectedTaskURL(state) {
			return state.taskURL;
		}
	},

	actions: {

		setActionsURL(context, taskURL){

			context.commit("SET_ACTION_URL", taskURL);

		},

		setProject(context, projectDetails){

			const projectId = projectDetails.projectId;
			const projectName = projectDetails.projectName;

			context.commit("SET_PROJECT_ID", projectId);
		  context.commit("SET_PROJECT_NAME", projectName);

		},

		fetchProjects(context) {

				axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token;
				return axios.get('/project').then(response => {

						const projectNames = response.data.map(project => project);
						context.commit("SET_PROJECTS", projectNames);

				});
		},

		getUserDetails(context) {

				axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token;
				return axios.get('/user').then(response => {


					const userid = response.data.id
						localStorage.setItem('loggedin_user', userid)
						context.commit("SET_USERID", userid);

					const username = response.data.name
						localStorage.setItem('loggedin_username', username)
						context.commit("SET_USERNAME", username);
					});
		},

		register(context, data) {
			return new Promise ((resolve, reject) => {
				axios.post('/register', {
					name: data.name,
					email: data.email,
					password: data.password,
				})
				.then(response => {

					resolve(response)

				})
				.catch(error => {

					reject(error);
				})
			})
		},

		destroyToken(context){
			axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token

			if (context.getters.loggedIn){
				return new Promise ((resolve, reject) => {
					axios.post('/logout')
					.then(response => {

						localStorage.removeItem('access_token')
						context.commit("DESTROY_TOKEN")
						context.commit("DESTROY_USERID")
						context.commit("DESTROY_USERNAME")
						context.commit("DESTROY_PROJECTS")
						resolve(response)

					})
					.catch(error => {
						localStorage.removeItem('access_token')
						context.commit("DESTROY_TOKEN")
						context.commit("DESTROY_USERID")
						context.commit("DESTROY_USERNAME")
						context.commit("DESTROY_PROJECTS")
						reject(error);
					})
				})

			}
		},

		 loadModules(context) {

					axios.defaults.headers.common['Authorization'] = 'Bearer ' + context.state.token
			    return axios.get('/modules').then(response => {

			        context.commit("SET_MODULES", response.data);
     	    	});
			},

			getTasks(context, moduleDetails){


				var moduleTitle = moduleDetails.moduleName;
				var moduleTitle = (moduleTitle === undefined) ? moduleTitle = 'Product & Service Analysis' : moduleTitle;
				//console.log(moduleTitle);

				var moduleId = moduleDetails.moduleId;
				var moduleId = (moduleId === undefined) ? moduleId = 1 : moduleId;

			 	return	axios.get(`project/${context.state.currentProjectId}/module/${moduleId}`)
						.then(response => {
							context.commit("SET_TASKS", response.data);

							context.commit("SET_MODULE_TITLE", moduleTitle);
						});
			},

			loadTasks(context, tasks){

			},

			loadActions(context){


			},

			retrieveToken(context, credentials){
				return new Promise ((resolve, reject) => {
					axios.post('/login', {
						username: credentials.username,
						password: credentials.password,
					})
					.then(response => {
						const token = response.data.access_token

						localStorage.setItem('access_token', token)
						context.commit("RETRIEVE_TOKEN", token)
						resolve(response)

					})
					.catch(error => {
						console.log(error);
						reject(error);
					})
				})
			},
	}

});

我的 app.js

// main.js

require('./bootstrap');

import Vue from 'vue';
import App from './App.vue';
import VueRouter from 'vue-router';
import VueAxios from 'vue-axios';
import axios from 'axios';
import routes from './routes';
import BootstrapVue from 'bootstrap-vue'
import { store } from './store/store';
import Vuex from 'vuex'


Vue.config.productionTip = false;

Vue.use(VueRouter);
Vue.use(VueAxios, axios);
Vue.use(BootstrapVue);
Vue.use(Vuex);

const router = new VueRouter({
  
  store,
  routes,
  mode: 'history'
})

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!store.getters.loggedIn) {
      next({
        name: 'login',
      })
    } else {
      next()
    }
  } else if (to.matched.some(record => record.meta.requiresVisitor)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (store.getters.loggedIn) {
      next({
        name: 'dashboard',
      })
    } else {
      next()
    }
  } else {
    next() // make sure to always call next()!
  }
})

new Vue({
    store: store,
    router,
    render: h => h(App)
}).$mount('#app');

import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';

如果引用@shazyriver:

我已经按照你的建议做了。我在const routes = [ ... 之前放置了一个console.log(./components/ProductServiceAnalysis/${state.taskURL}.vue);,它可以正确访问taskURL 属性并将其打印到控制台。但是,当它尝试从路由本身内部访问相同的属性时,它仍然会失败并显示“未定义状态”——即使它在 const routes = [ 之外访问时仍然有效:

查看控制台日志了解详情

【问题讨论】:

  • 您在构建时是否已经收到此错误?
  • 试试${state.taskURL}.vue ?
  • 您不应该像以前那样“导入”状态。这很可能是初始状态。您需要注释掉的映射器才能访问 Vuex 状态。此外,为什么需要在路由器定义中访问 Vuex 状态?
  • 1) 我在构建时没有收到错误消息。就在我执行尝试访问该组件的操作时。 2) ${state.taskURL}.vue 给出了同样的错误。 3)我需要访问状态,因为 taskURL 存储用于访问特定组件的 slug - 我正在使用动态导入来执行此操作
  • @RDowns 是:url 路由参数和taskURL 具有相同的值吗?

标签: javascript vue.js vuejs2 vue-router


【解决方案1】:

首先,您的配置和所有导入都是正确的。

这是一个很有趣的问题...我研究了一下,可以得出结论,webpack+babel的转译过程中存在一种bug。让我解释一下:

如果你检查你的包,你会发现在你的动态 import 行中有一个奇怪的未编译的 concat 表达式,像这样:("./".concat(state.taskURL,".vue")) - 但 state 应该用 webpack 帮助程序包装,但它不是t...看起来为 import 语句字符串插值跳过了模块解析。

最简单的解决方案是将导入的模块分配给某个变量并在import 语句中使用该变量(我建议使用完全配置的存储而不是状态):

import { store } from './store/store';
let storeVar = store;
//...
//...below
    component:  () => import(`./components/ProductServiceAnalysis/${storeVar.state.taskURL}.vue`),

在这种情况下,webpack 将正确处理模块。

附:我只用 webpack 创建了干净的项目,并尝试使用动态导入,它们被成功解决了......所以我想这个问题在另一个转译层中,也许是 babel。

附言如果我的解释不够清楚,请随时在 cmets 中提问。

【讨论】:

    【解决方案2】:

    你只需要像这样导入它:

    import store from './store/store.js'
    

    然后你可以像这样使用它:

    store.commit('increaseCounter')
    

    【讨论】:

      猜你喜欢
      • 2021-06-03
      • 2020-01-16
      • 2019-03-01
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 2021-04-10
      • 2021-04-26
      • 1970-01-01
      相关资源
      最近更新 更多