vuex项目中登录状态管理的实践过程

编辑: admin 分类: javascript 发布时间: 2021-11-17 来源:互联网
目录
  • 工具:
  • 登录场景:
  • 实践:
    • 场景1思考与实践
    • 场景2思考与实践
  • 总结

    工具:

    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)
        bgp服务器http://www.558idc.com/yz.html           //登陆成功后登陆状态设置为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登录状态管理内容请搜索hwidc以前的文章或继续浏览下面的相关文章希望大家以后多多支持hwidc!