从 Vuex 动作和组件更改路由
Posted
技术标签:
【中文标题】从 Vuex 动作和组件更改路由【英文标题】:Changing route from Vuex actions and components 【发布时间】:2017-12-01 18:00:06 【问题描述】:用户通过登录表单成功登录我的应用程序后。我想检查他们是否有个人资料。如果他们这样做,我想将他们发送到新闻页面。如果他们没有有一套,我希望它将他们重定向到“设置”页面。我将如何使用 Vuex 来做到这一点?
我想有几个选择:
1。负责重定向的组件? (感觉不对)
登录.vue
handleFormSubmit ()
this.$store.dispatch('loginFormSubmit', formData)
.then(() =>
// This feels a bit gross
this.$store.dispatch('getUserProfile')
.then(() => this.$router.push('/news'))
.catch(() => this.$router.push('/settings'))
)
.catch(() =>
this.loginError = true
)
2。我会在行动中承担责任吗?
用户操作.js
export const getUserProfile = (commit) =>
commit(types.USER_PROFILE_REQUEST)
const options =
url: `$API_URL/profile`,
method: 'GET'
return request(options)
.then((profileSettings) =>
// Would I change the router to News here??
commit(types.USER_PROFILE_SUCCESS, profileSettings)
return Promise.resolve(profileSettings)
)
.catch((error) =>
// Would I change the router to Settings here??
commit(types.UI_MENU_HIDE)
return Promise.reject(error)
)
export const loginFormSubmit = (dispatch, commit, email, password ) =>
console.log(email, password)
commit(types.USER_LOGIN_REQUEST)
const options =
url: `$API_URL/token`
return request(options)
.then((response) =>
dispatch('getUserProfile')
commit(types.USER_LOGIN_SUCCESS, response.token)
return Promise.resolve(response.token)
)
.catch((error) =>
commit(types.USER_LOGIN_FAILURE, error)
return Promise.reject(error)
)
3。也许它应该放在带有防护装置的路由器中?
登录.vue
handleFormSubmit ()
this.$store.dispatch('loginFormSubmit', formData)
.then(() => this.$router.push('/news'))
.catch(() =>
this.loginError = true
)
然后在我的路由器中:
const routes = [
path: 'news',
alias: '',
component: NewsView,
name: 'News',
meta: description: 'News feed page' ,
beforeEnter: (to, from, next) =>
store.dispatch('getUserProfile')
- .then((resp) =>
- // Profile set
- next()
- )
- .catch(() =>
- // No profile set
- next( name: 'settings' )
- )
,
]
4。监听商店变化,然后改变路线
computed:
isAuthenticated ()
return this.$store.getters.isAuthenticated
,
watch:
isAuthenticated ()
this.$router.push('/calendar')
,
methods:
handleSubmit (formData)
// Updates isAuthenticated on success
this.$store.dispatch('requestAuthToken', formData)
也许三四号最好?它感觉最干净,但很想知道你们的想法:D
感谢您提前抽出宝贵时间!
【问题讨论】:
你找到最好的方法了吗? 我真的很喜欢 #4 但 #3 可能也可以。实际上,我只是使用#4 来为自己解决这个问题。感谢您发布此信息。抱歉,您没有收到回复。我将这个原始问题标记为收藏。 【参考方案1】:我认为你想要你的想法 #2 的一个版本。为什么不这样:
-
你在
Login.vue
中调用handleFormSubmit()
,它会调度loginFormSubmit()
动作。也许此时为 UX 启用 Login.vue
中的加载状态。
如果用户可以登录,则调用getUserProfile()
,否则在Login.vue
中显示错误
getUserProfile()
从 API 获取
您可以在操作中通过 API 测试 response
,或者将 response
传递给执行此操作的单独突变。
如果用户有个人资料数据,更新state
和router.push('/pathToNews')
,否则更新router.push('/pathToSettings')
这里是简化的伪代码来说明这个概念:
// store
state:
userProfile:
,
mutations:
setUserProfile (state, payload)
state.userProfile = payload
,
actions:
getUserProfile()
let self = this
axios.get('$API_URL/token')
.then(function (response)
// test response against what is expected for a populated profile
if (response.data is a populated user profile)
self.commit('setUserProfile', response.data)
self.router.push('/news')
else
self.router.push('/settings')
)
.catch(function (error)
console.error(error);
// handle your error
)
.finally(function ()
// always executed
)
【讨论】:
【参考方案2】:我个人使用两种解决方案的组合来解决重定向/处理错误:
使用axios
拦截器获取最清晰的状态代码:
import axios from 'axios'
axios.interceptors.response.use(response => response, error =>
const status = error.response
const errorMessage = error.response.data.message
if (status === Constants.STATUS_CODE_ERROR_NOT_FOUND)
router.push('/404')
return
else if (status === Constants.STATUS_CODE_ERROR_UNAUTHENTICATED)
...
...
在动作中进行检查并在组件中返回以进行重定向或其他必要的操作。
另外,请考虑使用async/await
而不是then/catch
。
【讨论】:
【参考方案3】:我的流程:
-
组件
(this.$store.dispatch('getProfile'...)
动作 - 服务器 (const response = await fetch ...
)
提交对突变的响应
突变保存信息到商店
商店(唯一包含所有信息的地方)
组件(主动从 this.$store.state.user.hasProfile 获取数据并决定做什么)
总结:您发送请求 login, password,然后从服务器接收响应,例如 hasProfile: true/false
if(hasProfile)
// router to
else
// router to
【讨论】:
以上是关于从 Vuex 动作和组件更改路由的主要内容,如果未能解决你的问题,请参考以下文章
Vue.js - 从 API 获取数据并在 Vuex 状态更改时重新加载组件