如何在 vuex 的挂载函数中访问存储数据
Posted
技术标签:
【中文标题】如何在 vuex 的挂载函数中访问存储数据【英文标题】:How to access store data in mounted function in 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- max- />
<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" >
</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数据?
【问题讨论】:
【参考方案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。
这行得通..有些什么。谢谢!可能正在创建基于异步组件的答案.. 可以为您工作吗?以上是关于如何在 vuex 的挂载函数中访问存储数据的主要内容,如果未能解决你的问题,请参考以下文章