vuex項目中登錄狀態管理的實踐過程

工具:

chorme瀏覽器安裝Vue.js devtools方便調試

登錄場景:

頁面的導航處或其他地方有時會顯示用戶現在的登錄狀態,狀態可分為:未登錄,正在登錄(loading),登錄成功並顯示用戶名。

有些頁面是不需要登錄就可以讓用戶瀏覽的,但是有些頁面必須登錄才可以進入瀏覽。

實踐:

場景1思考與實踐

用vuex創建一個數據倉庫

//src目錄下新建一個store目錄,創建index.js如下
//創建數據倉庫
import Vuex from 'vuex';
import vue from 'vue';
import loginUser from 'loginUser.js'
Vue.use(Vuex)

const store = new Vuex.Store({
    modules: {  //modules 可以把不同的狀態單獨的放在一個對象裡面
        loginUser //是否正在登錄中
    },
    strict: true, //隻允許通過mutations改變狀態
});

設置登錄狀態loading和當前登錄用戶user

//創建一個loginUser.js,創建他的state/mutations/actions

//需要維護的狀態
state: {
       loading: false, //登錄狀態
       user: null, //當前登錄的用戶
       },
//計算屬性
getters: {
       status(state) {
           if (state.loading) {
               return 'loading'
           } else if (state.user) {
               return 'login'
           } else {
               return 'unLogin'
           }
       }
   },
 
 //改變loading和user狀態 
mutations: {
       //設置loading
       setLoading(state, msg) {
           state.loading = msg
       },
       //設置用戶
       setUser(state, msg) {
           state.user = msg
       }
   },
 
 //actions中提交改變的狀態  
 actions: {
       //登陸方法ctx相當於store
       async login(ctx, msg) {
           //登陸狀態設置為true
           ctx.commit("setLoading", true)
           const result = await xxxapi.login(msg.loginId, msg.loginPassword)
           if (result) {
               //登錄成功
               ctx.commit('setUser', result)
               //登陸成功後登陸狀態設置為false
               ctx.commit('setLoading', false)
           }
           //返回登陸是否成功
           return result
       },
       //判斷是否已登錄
       async isLogin(ctx) {
           //正在登錄中
           ctx.commit('setLoading', true)
           //調接口是否登陸
           const result = await xxxapi.isLogin();
           ctx.commit('setUser', result);
           ctx.commit('setLoading', false)
       },
       //註銷
       async logout(ctx) {
           ctx.commit('setLoading', false)
           await xxxapi.logout();
           ctx.commit('setUser', null);
           ctx.commit('setLoading', false)
       }
   },

頁面使用:

在登錄時,有一個登錄按鈕,按鈕的狀態我們就可以在Vuex的倉庫中獲取

<button :disabled="loading">{{ loading ? 'loading...' : '登錄' }}
</button>
computed: {
//在computed中封裝一下loading,不用每次調用都寫this.$store.state.loginUser這一堆
    // loading() {
    //  return this.$store.state.loginUser.loading;
    // }
    // 優化
    //輔助函數
    //import {mapState} from "vuex"
    ...mapState({
      loading: (state) => state.loginUser.loading
    })
  }

點擊按鈕的時候提交的時候分發action

async handleSubmit() {
      const result = await this.$store.dispatch("loginUser/login", {
        loginId: this.loginId,
        loginPassword: this.loginPassword
      });
      if (result) {
        //  登錄成功 路由跳轉
        const path = this.$route.query.url || '/'
        this.$router.push(path)
      }
    },

頁面的導航中切換顯示此時的登錄狀態[loading/login/unlogin]

  <!--      顯示頁面登錄狀態-->
<span v-if="status === 'loading'">正在登錄請稍等...</span>
​
<template v-else-if="status === 'login'">
    <span>當前登錄用戶{{user.name}}</span>
    <span @click="handleLogout">退出</span>
</template>
​
<router-link to="/login" v-else>
        登錄
</router-link>
  computed: {
...mapGetters("loginUser", ["status"]),
...mapState("loginUser", ["user"]),
}

登出時 更改狀態

async handleLogout(){
    await this.$store.dispatch("loginUser/logout")
    //跳轉到登陸頁面
    this.$route.push(/xxx)
},

每次頁面刷新需要檢測登錄狀態,在main.js中,也就是vue創建的時候就要判斷。
store.dispatch('loginUser/isLogin')

場景2思考與實踐

參考瞭後臺項目中的權限設置

總體設計:

刷新頁面後,在Vuex倉庫中先檢測此時登錄狀態–> 導航守衛(router.beforeEach)通過判斷meta中設置的參數檢測此頁面是否

需要登錄後才能查看 –>頁面渲染。

整體邏輯:

1.進入頁面時判斷此頁面是否需要登錄才能查看

2.判斷登錄狀態。有三種狀態如下:

  1. 如果已經登錄瞭就直接進入想去的頁面。
  2. 如果沒登錄,就進入登錄頁面讓用戶登錄。
  3. 如果狀態是加載中(loading),要傳入想去的頁面的路徑,並在加載中頁面監控Vuex倉庫中用戶登錄狀態的變化,監聽狀態變化完瞭之後,此時要不就是已經登錄瞭,要不就是沒有登錄的狀態,然後再走第1步判斷是否要登錄權限。

實踐:

在router中設置meta,如果auth為true就是需要登錄才能訪問

//routes.js中
import Home from "./xx/xx.vue"
export default[
{
      path:"/home",
    component:Home,
    meta: {
      auth: true, //需要權限才可以訪問的頁面
    }
}
]
在index.js中設置路由守衛
router.beforeEach((to, from, next) => {
    if (to.meta.auth) {
        // 需要登錄權限才可以訪問
        const result = store.getters["loginUser/status"]
        if (result === 'loading') {
            //    加載狀態,不知道有沒有登錄
            //    跳轉一個正在登錄中頁面,並且要在頁面中監控是否已經登錄成功瞭,要不然會永遠停留在這裡
            //    並且路由跳轉的時候得記錄你之前是從哪裡過來的,要不然不知道要跳轉到哪一個頁面
            next({
                path: '/loading', //去【正在登錄中】的頁面
                query: {
                    url: to.fullpath
                }
            })
        } else if (result === 'login') {
            // 登錄成功瞭
            next();
        } else {
            //    沒有登錄
           this.$message.info('你需要登錄');
             next({
                path: '/login', //去【正在登錄中】的頁面
                query: {
                    url: to.fullpath
                }
            })
        }
    } else {
        //不需要登錄權限就可以訪問的頁面
        next()
    }
})

在logining【正在登錄中】頁面中監控此時的狀態

created() {
  this.unWatch = this.$watch(() => this.$store.getters["loginUser/status"], (status) => {
    console.log('此時的狀態', status);
    if (status !== 'loading'){
      this.$router.push(this.$route.query.url || '/home').catch(() => {}
    }
  }, {
    immediate: true
  })
},
destroyed() {
  //取消監控
  this.unWatch()
}

總結

到此這篇關於vuex項目中登錄狀態管理的文章就介紹到這瞭,更多相關vuex登錄狀態管理內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: