【问题标题】:How to access store data in mounted function in vuex如何在 vuex 的挂载函数中访问存储数据
【发布时间】:2019-11-07 23:39:02
【问题描述】:

我有一个名为App.vue 的根组件。和另一个名为FileUploaderParent.vue 的组件。我正在调用调度承诺以将数据存储在商店中。我在挂载的生命周期钩子下调用调度。

另一方面,我试图在不同组件的挂载函数中访问存储的用户数据。它显示了未定义的错误

我知道,一种解决方法可以是在挂载的函数上调用相同的调度承诺。但是,感觉就像一个黑客,调度调用变得多余。

这是App.vue的代码:

<template>
  <v-app>
    <v-navigation-drawer  v-model="drawer" app temporary >
      <v-img :aspect-ratio="16/9" src="https://image.freepik.com/free-vector/spot-light-background_1284-4685.jpg">
        <v-layout pa-2 column fill-height class="lightbox gray--text">
          <v-spacer></v-spacer>
          <v-flex shrink>
            <!-- <div class="subheading">{{this.$store.getters.userData.name}}</div> -->
            <!-- <div class="body-1">{{this.$store.getters.userData.email}}</div> -->
          </v-flex>
        </v-layout>
      </v-img>
      <v-list>
        <template v-for="(item, index) in items">
          <v-list-tile :href="item.href" :to="{name: item.href}" :key="index">
            <v-list-tile-action>
              <v-icon light v-html="item.icon"></v-icon>                
            </v-list-tile-action>
            <v-list-tile-content>
              <v-list-tile-title v-html="item.title"></v-list-tile-title>
            </v-list-tile-content>
          </v-list-tile>
        </template>
      </v-list>
    </v-navigation-drawer>
    <v-toolbar color="white" light :fixed=true>
      <v-toolbar-side-icon @click.stop="drawer = !drawer"></v-toolbar-side-icon>
      <v-img :src="require('@/assets/mad_logo.png')" max-width="80px" max-height="41px"  />     
      <v-toolbar-title class="black--text justify-center" > <h1>MeshApp</h1></v-toolbar-title>
      <v-spacer></v-spacer>
      <v-avatar color="primary">
        <!-- <span class="white--text headline">{{this.avatar.slice(0,2)}}</span>          -->
      </v-avatar>   
    </v-toolbar>
    <v-content style="margin-top: 60px;">
      <v-fade-transition mode="out-in">
        <router-view></router-view>
      </v-fade-transition>
    </v-content>
  </v-app>  
</template>

<script>
export default {
  name: 'app',
  components: {

  },
  data() {
    return {   
      avatar: '',    
      drawer: false,
      items: [
        {
          href: 'home',
          router: true,
          title: 'home',
          icon: 'grid_on',
        },
        {
          href: 'view_volunteers',
          router: true,
          title: 'View Volunteer',
          icon: 'group'
        },
        {
          href: 'profile',
          router: true,
          title: 'profile',
          icon: 'account_circle',
        }, 
        {
          href: 'logout',
          router: true,
          title: 'Logout',
          icon: 'toggle_off',
        }

      ]
    }
  },
  props: [], 
  mounted() {
   this.$store.dispatch('getUserData').
    then(() => {      
     let findAvatar = this.$store.getters.userData.name.split(" ")
     let createAvatar = ''
     for(let i = 0; i < findAvatar.length; i++) {
       createAvatar = createAvatar + findAvatar[i].slice(0,1)
     }
     this.avatar = createAvatar
     console.log(this.avatar)
     // this.$store.dispatch('getUserId', id) 
   })    
  }   
}

</script>

<style scoped>

v-content {
  margin-top: 60px !important;
}
</style>

这是FileUploaderParent.vue的代码:

<template>
  <v-layout class="text-xs-center ">
    <v-flex>
      <image-input v-model="avatar">
        <div slot="activator">
          <v-avatar color = "primary" size="150px" v-ripple v-if="!avatar" class=" mb-3">
            <h1 class="white--text"><span>{{this.defaultAvatar}}</span></h1>
          </v-avatar>
          <v-avatar size="150px" v-ripple v-else class="mb-3">
            <img :src="avatar.imageURL" alt="avatar">
          </v-avatar>
        </div>
      </image-input>
      <v-slide-x-transition>
        <div v-if="avatar && saved == false">
          <!-- Stores the Image and changes the loader -->
          <v-btn  class="primary" @click="uploadImage" :loading="saving">Save Avatar</v-btn>
        </div>
      </v-slide-x-transition>
    </v-flex>
  </v-layout>
</template>

<script>
import ImageInput from './FileUploaderChild.vue'

export default {
  name: 'app',
  data () {
    return {
      defaultAvatar: '',
      avatar: null,
      saving: false,
      saved: false
    }
  },
  mounted() {
     this.$store.dispatch('getUserData').
    then(() => {
      let findAvatar = this.$store.getters.userData.name.split(" ")
      let createAvatar = ''
      for(let i = 0; i < findAvatar.length; i++) {
        createAvatar = createAvatar + findAvatar[i].slice(0,1)
      }
      this.defaultAvatar = createAvatar
    })
  },
  components: {
    ImageInput: ImageInput
  },
  watch:{
    avatar: {
      handler: function() {
        this.saved = false
      },
      deep: true
    }
  },
  methods: {
    uploadImage() {
      this.saving = true
      setTimeout(() => this.savedAvatar(), 1000)
    },
    savedAvatar() {
      this.saving = false
      this.saved = true
    }
  }
}
</script>

<style>

</style>

这是商店的样子: store.js

actions: {
        getUserData(context)  {
            return new Promise((resolve, reject) => {
                axios.get('http://someurl.in/api/v1/users/'+this.state.userId, {
                    headers: {
                        'Content-Type': 'application/json'               
                    },
                    auth: {
                        username: 'someusername',
                        password: 'pass'
                    }    
                }).
                then(response => {
                    context.commit('storeUserData', response.data.data.users)                    
                    resolve(response);  // Let the calling function know that http is done. You may send some data back
                }).catch(error => {
                    reject(error);
                })        
            })
        }
},
mutations: {
        storeUserData(state, data) {
            state.userData = data
        }
}

这是错误的样子:

如何在mounted函数下访问FileUploaderParent.vue中的store数据?

【问题讨论】:

    标签: javascript vue.js components vuex


    【解决方案1】:

    您编写的代码似乎是正确的,但如果您仍然需要答案,您可以使用 watch on store

    this.$store.watch(() => this.$store.state.userData, async () => {
     //do your code here 
    });
    

    【讨论】:

      【解决方案2】:

      this.$store.getters 指的是您的 Vuex 商店中的吸气剂。您的 Vuex 商店中没有吸气剂 - 至少在您的示例中看不到任何吸气剂。 (https://vuex.vuejs.org/guide/getters.html)

      【讨论】:

      • 我假设 OP 从代码中省略了 getters 部分,并且他具有同名的此属性 (userData)。否则,这可能就是答案!
      • 是的,也许——但还有一个因素是其他人(比如我)看不到的。然后getter 可以返回任何东西——甚至是undefined。解决这个问题会很困难...... :)
      【解决方案3】:

      如何添加一个检查以确定是否需要 API 调用:

      actions: {
        getUserData(context) {
          return new Promise((resolve, reject) => {
            // Be sure to set the default value to `undefined` under the `state` object.
            if (typeof this.state.userData === 'undefined') {
              axios
                .get('http://someurl.in/api/v1/users/' + this.state.userId, {
                  headers: {
                    'Content-Type': 'application/json'
                  },
                  auth: {
                    username: 'someusername',
                    password: 'pass'
                  }
                })
                .then(response => {
                  context.commit('storeUserData', response.data.data.users);
                  resolve(response.data.data.users);
                })
                .catch(error => {
                  reject(error);
                });
            }
            else {
              resolve(this.state.userData);
            }
          })
        }
      }
      

      【讨论】:

      • 它仍然感觉像是一种解决方法......我觉得它与生命周期挂钩有关。但是,我想不通。 Somewhere the reason is the component is getting mounted before the API call gets completed.
      • 如果您想订购组件安装,您可能需要查看async component
      • 这行得通..有些什么。谢谢!可能正在创建基于异步组件的答案.. 可以为您工作吗?
      猜你喜欢
      • 1970-01-01
      • 2022-01-09
      • 2020-08-17
      • 2018-11-10
      • 2017-08-18
      • 1970-01-01
      • 1970-01-01
      • 2021-07-22
      • 2019-11-08
      相关资源
      最近更新 更多