【问题标题】:Vuex getter returns undefinedVuex getter 返回未定义
【发布时间】:2018-11-16 18:58:16
【问题描述】:

我有一个使用 vex 存储站点范围数据的 vue 应用程序,我获取用户信息并将其置于创建生命周期方法之前的状态,如下所示:

const app = new Vue({
    el: '#app',
    store,
    beforeCreate(){
        store.dispatch('currentUser');
    }
});

在我的用户模块中,我有一个获取用户名称的 getter,如下所示:

const getters = {
    getName(state){
        return state.user.name;
    }
};

在我的组件中,我试图访问 getter 以在组件中显示用户名。当我查看 Vue Chrome 开发工具时,getter 不是未定义的,但是当我控制台记录 getter 结果时,它显示为未定义。

mounted(){
    console.log(store.getters.getName);
},

似乎组件在加载状态之前正在加载。我正在使用 axios 获取用户信息。我真的很困惑如何解决这个问题,因为我无法尽快调用该操作来获取用户数据。

如果在我的 getter 方法中我这样做:

state.user

我明白了:

{ "id": 1, "name": "Test" }

但是当我尝试获取名称时,我得到了未定义

这里是商店:

import axios from "axios/index";

const state = {
    user: {},
};

const mutations = {
    FETCH_USER(state,user){
        state.user = user;
    },
    UPDATE_AVATAR(state,avatar){
        state.user.avatar = avatar;
    }
};

const getters = {
    getName(state){
      return state.user.name
    },
    avatar(state){
        return state.user.avatar;
    },
    userSocialNetworks(state){
        //return state.user.social_networks
    },
    schoolName(state){
        return state.user.school
    },
    schoolAbout(state){
        return state.user.school.about
    },
    schoolAddress(state){
        return state.user.school.address
    }
};

const actions = {
    currentUser: ({commit}) => {
        axios.get('/api/user').then(response => {
            commit('FETCH_USER', response.data);
        });

    }
}

export default {
    state,
    getters,
    actions,
    mutations

}


 {"user":{"user":{"name":"Test","email":"test@test.edu","avatar":"http://www.gravatar.com/avatar/xxxx=300","city":null,"state":null,"zip":null,"address":null,"lat":null,"long":null,"role":"school","school":{"id":1,"about":null,"header":null,"name":"Test","user_id":1,"created_at":"2018-06-06 19:48:16","updated_at":"2018-06-06 19:48:16"},"following":[],"followers":[],"social_networks":[{"id":4,"user_id":1,"social_network_id":1,"network_url":"test.com/k","created_at":"2018-06-06 23:11:09","updated_at":"2018-06-06 23:15:19"},{"id":5,"user_id":1,"social_network_id":2,"network_url":"test.com/k","created_at":"2018-06-06 23:15:19","updated_at":"2018-06-06 23:15:19"},{"id":6,"user_id":1,"social_network_id":5,"network_url":"test.com/k","created_at":"2018-06-06 23:16:15","updated_at":"2018-06-06 23:16:15"}]}},"socialNetowrks":{"available_networks":[{"id":1,"network_name":"Facebook","created_at":null,"updated_at":null},{"id":2,"network_name":"Instagram","created_at":null,"updated_at":null},{"id":5,"network_name":"Twitter","created_at":null,"updated_at":null}]}}

【问题讨论】:

  • 你需要在组件中使用this.$store.getters.getName
  • 有什么区别
  • 区别是一个未定义,另一个不是
  • @Derek 我以这种方式使用存储时遇到此错误 挂载钩子中的错误:“TypeError:无法读取未定义的属性'名称'”
  • 这意味着state.user 未定义

标签: javascript vue.js vuex


【解决方案1】:

您在这里面临两个大问题:

  1. 您不应直接在 vuex 存储中更新对象,否则您将失去反应性

因此,请确保正确声明所有状态并分配给对象而不是覆盖它们

import assignDeep from 'assign-deep'; //Since you have nested structure you will need this

const state = {
    user: {
       name: '',
       school: {
          about: '',
          address: '',
       },
       // Make sure all properties are defined
    },

};

const mutations = {
    FETCH_USER(state,user){
        assignDeep(state.user, user);
    },
    UPDATE_AVATAR(state,avatar){
        state.user.avatar = avatar;
    }
};
  1. 您正在尝试访问在状态上异步定义的属性并同步使用它(在它存在之前)

首先使用vuex的mapGetters实用程序,使用起来更方便

import { mapGetters } from 'vuex';
//... In component definition
computed: {
  ...mapGetters({name: 'getName'})
}

由于这是一个 vue 计算属性,您的组件将在它被定义时重新渲染,并且一切都应该正确显示您只需要确保在它为空时处理这种情况,并且可能会显示加载屏幕直到它是

例如

<template>
  <div v-if="!name" class="loading"></div>
  <div v-else>{{name}}</div>
<template>

您也可以等待属性更新

不要在挂载的钩子中使用它,因为它仍然是那里的默认值

根据您的需要使用watcher or a computed property

watch: {
  name: {
    handler(name, oldName) {
      if (name) {
        //Do something
      }
    },
    immediate: true
  }
}

【讨论】:

    【解决方案2】:

    首先,beforeCreate 钩子中的方法还没有被初始化。解决这个问题的最简单方法是使用 created 挂钩:

    const app = new Vue({
        el: '#app',
        store,
        created(){
            store.dispatch('currentUser'); // considering you have properly imported and exported vuex
        }
    });
    

    在你的组件中

    import {mapGetters} from 'vuex';
    
    export default {
      computed: {
        ...mapGetters(['getName'])
      }
    }
    

    【讨论】:

    • 即使这样也不行 SchoolName方法可以返回对象但不能返回name属性。
    【解决方案3】:

    尝试在store中声明具体的变量来正确初始化数据:

    const state = {
        user: {
            name: '',
            avatar: '',
            school: '',
            ...
        },
    };
    

    在我这样做之前,我遇到了与您描述的相同的问题。

    【讨论】:

      【解决方案4】:

      你可以试试这个:

      mounted() {
        setTimeout(() => {
          console.log(store.getters.getName);
        }, 400);
      },
      

      【讨论】:

      • setTimeout 真的是个坏习惯。-)
      猜你喜欢
      • 2019-07-31
      • 2020-10-05
      • 2021-05-04
      • 2020-01-26
      • 2021-09-30
      • 2021-02-01
      • 2018-05-12
      • 2020-11-03
      • 2011-10-19
      相关资源
      最近更新 更多