vuex項(xiàng)目中登錄狀態(tài)管理的實(shí)踐過(guò)程
工具:
chorme瀏覽器安裝Vue.js devtools方便調(diào)試
登錄場(chǎng)景:
頁(yè)面的導(dǎo)航處或其他地方有時(shí)會(huì)顯示用戶(hù)現(xiàn)在的登錄狀態(tài),狀態(tài)可分為:未登錄,正在登錄(loading),登錄成功并顯示用戶(hù)名。
有些頁(yè)面是不需要登錄就可以讓用戶(hù)瀏覽的,但是有些頁(yè)面必須登錄才可以進(jìn)入瀏覽。
實(shí)踐:
場(chǎng)景1思考與實(shí)踐
用vuex創(chuàng)建一個(gè)數(shù)據(jù)倉(cāng)庫(kù)
//src目錄下新建一個(gè)store目錄,創(chuàng)建index.js如下 //創(chuàng)建數(shù)據(jù)倉(cāng)庫(kù) import Vuex from 'vuex'; import vue from 'vue'; import loginUser from 'loginUser.js' Vue.use(Vuex) const store = new Vuex.Store({ modules: { //modules 可以把不同的狀態(tài)單獨(dú)的放在一個(gè)對(duì)象里面 loginUser //是否正在登錄中 }, strict: true, //只允許通過(guò)mutations改變狀態(tài) });
設(shè)置登錄狀態(tài)loading和當(dāng)前登錄用戶(hù)user
//創(chuàng)建一個(gè)loginUser.js,創(chuàng)建他的state/mutations/actions //需要維護(hù)的狀態(tài) state: { loading: false, //登錄狀態(tài) user: null, //當(dāng)前登錄的用戶(hù) }, //計(jì)算屬性 getters: { status(state) { if (state.loading) { return 'loading' } else if (state.user) { return 'login' } else { return 'unLogin' } } }, //改變loading和user狀態(tài) mutations: { //設(shè)置loading setLoading(state, msg) { state.loading = msg }, //設(shè)置用戶(hù) setUser(state, msg) { state.user = msg } }, //actions中提交改變的狀態(tài) actions: { //登陸方法ctx相當(dāng)于store async login(ctx, msg) { //登陸狀態(tài)設(shè)置為true ctx.commit("setLoading", true) const result = await xxxapi.login(msg.loginId, msg.loginPassword) if (result) { //登錄成功 ctx.commit('setUser', result) //登陸成功后登陸狀態(tài)設(shè)置為false ctx.commit('setLoading', false) } //返回登陸是否成功 return result }, //判斷是否已登錄 async isLogin(ctx) { //正在登錄中 ctx.commit('setLoading', true) //調(diào)接口是否登陸 const result = await xxxapi.isLogin(); ctx.commit('setUser', result); ctx.commit('setLoading', false) }, //注銷(xiāo) async logout(ctx) { ctx.commit('setLoading', false) await xxxapi.logout(); ctx.commit('setUser', null); ctx.commit('setLoading', false) } },
頁(yè)面使用:
在登錄時(shí),有一個(gè)登錄按鈕,按鈕的狀態(tài)我們就可以在Vuex的倉(cāng)庫(kù)中獲取
<button :disabled="loading">{{ loading ? 'loading...' : '登錄' }} </button> computed: { //在computed中封裝一下loading,不用每次調(diào)用都寫(xiě)this.$store.state.loginUser這一堆 // loading() { // return this.$store.state.loginUser.loading; // } // 優(yōu)化 //輔助函數(shù) //import {mapState} from "vuex" ...mapState({ loading: (state) => state.loginUser.loading }) }
點(diǎn)擊按鈕的時(shí)候提交的時(shí)候分發(fā)action
async handleSubmit() { const result = await this.$store.dispatch("loginUser/login", { loginId: this.loginId, loginPassword: this.loginPassword }); if (result) { // 登錄成功 路由跳轉(zhuǎn) const path = this.$route.query.url || '/' this.$router.push(path) } },
頁(yè)面的導(dǎo)航中切換顯示此時(shí)的登錄狀態(tài)[loading/login/unlogin]
<!-- 顯示頁(yè)面登錄狀態(tài)--> <span v-if="status === 'loading'">正在登錄請(qǐng)稍等...</span> <template v-else-if="status === 'login'"> <span>當(dāng)前登錄用戶(hù){{user.name}}</span> <span @click="handleLogout">退出</span> </template> <router-link to="/login" v-else> 登錄 </router-link> computed: { ...mapGetters("loginUser", ["status"]), ...mapState("loginUser", ["user"]), }
登出時(shí) 更改狀態(tài)
async handleLogout(){ await this.$store.dispatch("loginUser/logout") //跳轉(zhuǎn)到登陸頁(yè)面 this.$route.push(/xxx) }, 每次頁(yè)面刷新需要檢測(cè)登錄狀態(tài),在main.js中,也就是vue創(chuàng)建的時(shí)候就要判斷。 store.dispatch('loginUser/isLogin')
場(chǎng)景2思考與實(shí)踐
參考了后臺(tái)項(xiàng)目中的權(quán)限設(shè)置
總體設(shè)計(jì):
刷新頁(yè)面后,在Vuex倉(cāng)庫(kù)中先檢測(cè)此時(shí)登錄狀態(tài)–> 導(dǎo)航守衛(wèi)(router.beforeEach)通過(guò)判斷meta中設(shè)置的參數(shù)檢測(cè)此頁(yè)面是否
需要登錄后才能查看 -->頁(yè)面渲染。
整體邏輯:
1.進(jìn)入頁(yè)面時(shí)判斷此頁(yè)面是否需要登錄才能查看
2.判斷登錄狀態(tài)。有三種狀態(tài)如下:
- 如果已經(jīng)登錄了就直接進(jìn)入想去的頁(yè)面。
- 如果沒(méi)登錄,就進(jìn)入登錄頁(yè)面讓用戶(hù)登錄。
- 如果狀態(tài)是加載中(loading),要傳入想去的頁(yè)面的路徑,并在加載中頁(yè)面監(jiān)控Vuex倉(cāng)庫(kù)中用戶(hù)登錄狀態(tài)的變化,監(jiān)聽(tīng)狀態(tài)變化完了之后,此時(shí)要不就是已經(jīng)登錄了,要不就是沒(méi)有登錄的狀態(tài),然后再走第1步判斷是否要登錄權(quán)限。
實(shí)踐:
在router中設(shè)置meta,如果auth為true就是需要登錄才能訪(fǎng)問(wèn)
//routes.js中 import Home from "./xx/xx.vue" export default[ { path:"/home", component:Home, meta: { auth: true, //需要權(quán)限才可以訪(fǎng)問(wèn)的頁(yè)面 } } ] 在index.js中設(shè)置路由守衛(wèi) router.beforeEach((to, from, next) => { if (to.meta.auth) { // 需要登錄權(quán)限才可以訪(fǎng)問(wèn) const result = store.getters["loginUser/status"] if (result === 'loading') { // 加載狀態(tài),不知道有沒(méi)有登錄 // 跳轉(zhuǎn)一個(gè)正在登錄中頁(yè)面,并且要在頁(yè)面中監(jiān)控是否已經(jīng)登錄成功了,要不然會(huì)永遠(yuǎn)停留在這里 // 并且路由跳轉(zhuǎn)的時(shí)候得記錄你之前是從哪里過(guò)來(lái)的,要不然不知道要跳轉(zhuǎn)到哪一個(gè)頁(yè)面 next({ path: '/loading', //去【正在登錄中】的頁(yè)面 query: { url: to.fullpath } }) } else if (result === 'login') { // 登錄成功了 next(); } else { // 沒(méi)有登錄 this.$message.info('你需要登錄'); next({ path: '/login', //去【正在登錄中】的頁(yè)面 query: { url: to.fullpath } }) } } else { //不需要登錄權(quán)限就可以訪(fǎng)問(wèn)的頁(yè)面 next() } })
在logining【正在登錄中】頁(yè)面中監(jiān)控此時(shí)的狀態(tài)
created() { this.unWatch = this.$watch(() => this.$store.getters["loginUser/status"], (status) => { console.log('此時(shí)的狀態(tài)', status); if (status !== 'loading'){ this.$router.push(this.$route.query.url || '/home').catch(() => {} } }, { immediate: true }) }, destroyed() { //取消監(jiān)控 this.unWatch() }
總結(jié)
到此這篇關(guān)于vuex項(xiàng)目中登錄狀態(tài)管理的文章就介紹到這了,更多相關(guān)vuex登錄狀態(tài)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue數(shù)據(jù)更新但頁(yè)面沒(méi)有更新的多種情況問(wèn)題及解決
這篇文章主要介紹了Vue數(shù)據(jù)更新但頁(yè)面沒(méi)有更新的多種情況問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07解決Vue.js Devtools未檢測(cè)到Vue實(shí)例的問(wèn)題
在開(kāi)發(fā)Vue.js應(yīng)用時(shí),Vue.js Devtools是一個(gè)不可或缺的調(diào)試工具,然而,有時(shí)我們可能會(huì)遇到“Vue.js not detected”的提示,這意味著Vue.js Devtools未能成功識(shí)別和連接到我們的Vue應(yīng)用,本文將詳細(xì)解析這個(gè)問(wèn)題,并提供相應(yīng)的解決步驟與代碼示例,需要的朋友可以參考下2024-01-01Vue3+NodeJS+Soket.io實(shí)現(xiàn)實(shí)時(shí)聊天的示例代碼
本文主要介紹了Vue3+NodeJS+Soket.io實(shí)現(xiàn)實(shí)時(shí)聊天的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01vue3?使用defineAsyncComponent與component標(biāo)簽實(shí)現(xiàn)動(dòng)態(tài)渲染組件思路詳解
這篇文章主要介紹了vue3?使用defineAsyncComponent與component標(biāo)簽實(shí)現(xiàn)動(dòng)態(tài)渲染組件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03前端vue3項(xiàng)目中百度地圖的使用api以及操作實(shí)例
最近項(xiàng)目要用到百度地圖api,好久沒(méi)用到地圖,就百度了一番,但是找了好幾篇文章,發(fā)現(xiàn)都沒(méi)辦法成功實(shí)現(xiàn),現(xiàn)將方法記錄如下,下面這篇文章主要給大家介紹了關(guān)于前端vue3項(xiàng)目中百度地圖的使用api以及操作實(shí)例,需要的朋友可以參考下2023-05-05vue父組件向子組件傳遞多個(gè)數(shù)據(jù)的實(shí)例
下面小編就為大家分享一篇vue父組件向子組件傳遞多個(gè)數(shù)據(jù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-03-03Vue中addEventListener()?監(jiān)聽(tīng)事件案例講解
這篇文章主要介紹了Vue中addEventListener()?監(jiān)聽(tīng)事件案例講解,包括語(yǔ)法講解和事件冒泡或事件捕獲的相關(guān)知識(shí),本文結(jié)合示例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2022-12-12