带有NodeJS,Express和MongoDB的内置API,使用JWT和Cookies进行用户身份验证。 使用商店(vuex)从具有axios服务的API中获取用户数据。在商店文件夹中创建了auth.js,创建了fetchData操作,该操作从后端(axios.get(apiRoute))获取数据并将用户设置为状态。 想要使用nuxtServerInit做到这一点,所以我在存储文件夹中创建了index.js文件。添加了空状态和动作。动作包含nuxtServerInit,它使用dispatch()来调用auth.js中的fetchData方法。
毕竟,它根本不起作用。例如:用户已登录,但帐户页面未使用用户数据(名称,电子邮件,图像等)呈现。
我尝试从auth.js中的fetchData操作返回一个Promise,但它不起作用。 我也尝试在index.js文件的现场设置fetchData操作并直接在其上调用dispatch。
store / auth.js
// Importing Files
import axios from 'axios';
// State
export const state = () => ({
user: null
});
// Mutations
export const mutations = {
SET_USER (store, data) {
store.user = data
},
RESET_USER (store) {
store.user = null
}
};
// Actions
export const actions = {
// Fetch User Account
async fetchData ({ commit }) {
try {
const response = await axios.get('http://localhost:3000/api/v1/users/account');
commit('SET_USER', response.data.doc);
return response;
} catch (err) {
commit('RESET_USER');
}
}
};
store / index.js
// State
export const state = () => ({
});
// Actions
export const actions = {
async nuxtServerInit({ dispatch }) {
console.log('Testing');
const res = dispatch('auth/fetchData');
return res;
}
};
components / Settings.vue
<template>
<section class="data-block-wrap" v-if="user">
<BlockHeader :blockHeaderName="`Welcome Back, ${user.name.split(' ')[0]}`" btnText="More Details" />
<img :src="getPhotoUrl(user.photo)" alt="User Photo" class="user-data__image">
<p class="user-data__short-bio">{{ user.shortBio }}</p>
</section>
</template>
<script>
export default {
// Computed
computed: {
user() {
return this.$store.state.auth.user;
}
}
...
};
</script>
我希望可以在Vue组件上正确呈现用户数据,但目前根本无法正常工作。渲染是静态的,没有显示来自数据库/ api的数据。
编辑/更新
在default.vue文件(所有组件的“父级”文件)的created()钩子上调用fetchData时,App会正确呈现用户数据。
default.vue
<template>
<div class="container">
<TopNav />
<SideNav />
<nuxt />
</div>
</template>
// Importing Components
import TopNav from '@/components/navigation/TopNav';
import SideNav from '@/components/navigation/SideNav';
import axios from 'axios';
import { mapActions } from 'vuex';
export default {
components: {
TopNav,
SideNav
},
methods: {
// Map Actions
...mapActions('auth', ['fetchData']),
async checkUser() {
const user = await this.fetchData();
},
},
// Lifecycle Method - Created
created() {
this.checkUser();
}
}
</script>
答案 0 :(得分:1)
这里似乎发生了一些非常有趣的事情。问题是从nuxtServerInit()内部调用axios.get('http://localhost:3000/api/v1/users/account')
。
这实际上导致了无限递归。 nuxtServerInit会对http://localhost:3000
进行调用,该击中相同的服务器,再次运行nuxtServerInit,然后调用http://localhost:3000
,依此类推,直到JavaScript堆内存不足为止。
为此,请使用fetch方法,而不是为此使用nuxtServerInit:
fetch方法用于在呈现页面之前填充商店, 就像asyncData方法一样,除了它没有设置组件 数据。
注意:您无法访问fetch中的Nuxt组件,因此必须使用context对象而不是“ this”
// inside your page component
export default {
fetch (context) {
return context.store.dispatch('auth/fetchData');
}
}
一般规则:
答案 1 :(得分:1)
The solution to this question is to use the NuxtServerInt Action this way inside your store.js
1. you will need to run npm install cookieparser and npm install js-cookie
const cookieparser = process.server ? require('cookieparser') : undefined
export const state = () => {
return {
auth: null,
}
}
export const mutations = {
SET_AUTH(state, auth) {
state.auth = auth
},
}
export const actions = {
nuxtServerInit({ commit }, { req }) {
let auth = null
if (req.headers.cookie) {
try {
const parsed = cookieparser.parse(req.headers.cookie)
auth = parsed.auth
} catch (err) {
console.log('error', err)
}
}
commit('SET_AUTH', auth)
},
}
Then in your login page component, you call your backend API, just like this
import AuthServices from '@/ApiServices/AuthServices.js'
import swal from 'sweetalert'
const Cookie = process.client ? require('js-cookie') : undefined
async onSubmit() {
try {
const body = {
email: this.email,
password: this.password,
}
const res = await AuthServices.loginUrl(body)
console.log('res', res)
console.log('res', res.data.message)
setTimeout(() => {
// we simulate the async request with timeout.
const auth = {
accessToken: res.data.payload.token, // from your api call, you get the user token
userData: res.data.payload.user,
}
swal('Logged in', `${res.data.message}`, 'success')
this.email = this.password = ''
this.$refs.loginForm.reset()
this.$store.commit('setAuth', auth) // mutating to store for client rendering
Cookie.set('auth', auth) // saving token in cookie for server rendering
this.$router.push('/')
}, 1000)
} catch (error) {
console.log('error', error)
swal('Error!', `${error.message}`, 'error')
}
},
your AuthServices.js looks like this
import axios from 'axios'
const apiClient = axios.create({
baseURL: `http://localhost:3000`,
})
export default {
loginUrl(body) {
return apiClient.post('/login', body, {
headers: {
'Content-Type': 'application/json',
},
})
}
}
then you get the user data using computed in the navbar or say dashboard e.g to say Hi,Xavier
inside where you want place the user data, just add this
<template>
<section>
<p class="firtname_data">Hi, {{ user.firstnam }}</p>
</section>
</template>
<script>
export default {
// Computed
computed: {
user() {
return this.$store.state.auth.userData
}
...
};
</script>
Hope this help... it worked for me