尚品汇(八)

本文详细介绍了前端应用中的登录注册流程,包括获取验证码、注册、登录的实现,以及用户信息的持久化存储和全局路由守卫的使用。在注册和登录过程中,涉及Vuex状态管理,数据验证,以及服务器交互。同时,讨论了如何在用户登录后通过全局路由守卫判断用户状态,确保只有已登录用户才能访问特定路由。此外,还涵盖了在用户退出登录时清除本地存储的token和用户信息。
摘要由CSDN通过智能技术生成

一、登录注册静态组件

assets文件夹放置全部组件共用静态资源,打包后在js中

二、注册业务

const {phone}= this相当于 const phone = this.phone

//获取验证码按钮的回调
    async getCode() {
      const { phone } = this;
      //先不处理表单验证业务
      if (phone) {
        try {
          //获取验证码成功
          await this.$store.dispatch("getCode", phone);
          //修改VC身上的code属性,让验证码自动展示
          this.code = this.$store.state.user.code;
        } catch (error) {}
      }
    },
 //获取验证码
     async getCode({ commit, state, dispatch }, phone) {
          let result = await reqGetCode(phone);
          if (result.code == 200) {
               commit('GETCODE', result.data);
               return 'ok';
          } else {
               return Promise.reject();
          }
     }
 GETCODE(state, code) {
          state.code = code;
     },
  //注册按钮的回调
    async register() {
      //解构出参数
      const { phone, code, password, password1 } = this;
      //目前不做表单验证
      if (phone && code && password == password1) {
        //通知vuex发请求,进行用户的注册
        try {
          //注册成功
          await this.$store.dispatch("registerUser", { phone, code, password });
          //让用户跳转到登录页面进行登录
          this.$router.push('/login');
        } catch (error) {
          //注册失败
          alert(error.message);
        }
      }
    },
 //注册用户的地方
     async registerUser({ commit, state, dispatch }, obj) {
          //注册接口没有返回data,不需要提交mutation
          let result = await reqRegister(obj);
          if (result.code == 200) {
               //注册成功
               return 'ok';
          } else {
               //注册失败
               return Promise.reject(new Error(result.message));
          }
     }

三、登录

登陆成功的时候,后台为了区分你这个用户是谁,服务器下发token,前台持久化存储token,前台带着token找服务器要用户信息进行展示

当用户注册完成,用户登录向服务器发送请求,登陆成功获取到token,存在仓库中(非持久化),路由跳转到home首页
在首页组件挂载完毕后,派发action获取用户信息,展示在header组件内
但是,一刷新,home首页获取不到用户信息
使用全局路由守卫解决

持久化token

阻止表单的默认行为,点击自动跳转页面

<button class="btn" @click.prevent="login">&nbsp;&nbsp;</button>```
```javascript

 //登录按钮
    async login() {
      //整理参数
      const { phone, password } = this;
      //在发登录请求
      try {
        //登录成功
        await this.$store.dispatch("userLogin", { phone, password });
        //若地址栏中有redirect参数,则跳往该地址
        let goPath = this.$route.query.redirect||'/home';
        //跳转到首页
        this.$router.push(goPath);
      } catch (error) {
        alert(error.message);
      }
    },

vuex的数据存储是非持久化的,所以需要将token存入本地存储

 //用户登录的地方:非常非常重要
     async userLogin({ commit, state, dispatch }, data) {
          //接口说明:后台老师目前登录接口返回数据不正确的,以后工作的时候登录接口成功,返回格式100%和相面例子一样的!!!
          /*
            举例子
             {
                   code:200,
                   data:{
                        token:'1e4vdadhajkhdakj6sahdajk'
                   },
                   message:'登录成功'
             }
          */
          let result = await reqUserLogin(data);
          //登录成功
          if (result.code == 200) {
               commit('SET_TOKEN', result.data.token);
               //以后开发的时候:经常的登录的成功获取token【持久化存储】
               localStorage.setItem('TOKEN', result.data.token);
               return 'ok';
          } else {
               //登录失败
               return Promise.reject(new Error(result.message));
          }

     }

1.用户携带token获取用户信息

请求拦截器中设置请求头携带token

 //获取用户信息
     async getUserInfo({ commit, state, dispatch }) {
          let result = await reqUserInfo();
          if (result.code == 200) {
               commit('SET_USERINFO', result.data.nickName);
               return 'ok';
          } else {
               return Promise.reject();
          }
     },

 SET_USERINFO(state, nickName) {
          state.nickName = nickName;
     },
 <!-- 没有登录:显示登录与注册 -->
            <p v-if="!$store.state.user.nickName">
              <span></span>
              <!-- <a href="###">登录</a> -->
              <!-- 
                声明式导航,当然你也可以使用编程式导航,因为不管是那个导航,都可以实现路由跳转,
                但是最后为什么选择声明式导航,没有任何业务、逻辑
               -->
              <router-link to="/login">登录</router-link>
              <router-link class="register" to="/register">注册</router-link>
            </p>
            <!-- 如果登录显示的是用户名字与退出登录 -->
            <p v-else>
              <a>{{$store.state.user.nickName}}</a>
              <a class="register" @click="logout">退出登录</a>
            </p>

3.解决登录后的用户信息展示

退出登录
1.通知服务器退出登录
2.清除项目中的数据(userInfo token)

 //退出登录的按钮的回调
    logout(){
       //派遣action退出登录
       this.$store.dispatch('logout');
    }

user.js
服务器中清除

//退出登录的业务
     async logout({ commit, state, dispatch }) {
          //发请求通知服务器销毁当前token【学生证】
          //清除服务器中的登录
          let result = await reqUserLogout();
          if (result.code == 200) {
               commit('CLEAR');
               return 'ok';
          } else {
               return Promise.reject(new Error(result.message));
          }
     }

清除本地存储

 CLEAR(state) {
          //清除仓库相关用户信息
          state.token = '';
          state.nickName = '';
          //本地存储令牌清空
          localStorage.removeItem('TOKEN');
     }

//全局守卫:只要项目中有任何路由变化,全局守卫都会进行拦截【符合条件走你,不符合条件不能访问】

//全局守卫:全局前置守卫【访问之前进行触发】


//全局前置守卫
router.beforeEach(async (to, from, next) => {
    //to:去的那个路由的信息
    //from:从那个路由而来的信息
    //next:放行函数!!!!!! 
    //第一种:next(),放行函数,放行到指定的路由!!!
    //第二种:next(path),守卫指定放行到那个路由去?

    //用户是否登录:取决于仓库里面是否有token!!!
    //每一次路由跳转之前需要用有用户信息在跳转,没有发请求获取用户信息在跳转!!!!
    //token
    let hasToken = store.state.user.token;
    //用户信息
    let hasNickName = store.state.user.nickName;
    //用户登录
    if (hasToken) {
        //用户登录了,不能去login
        if (to.path == "/login") {
            next('/home');
        } else {
            //用户登陆了,而且还有用户信息【去的并非是login】
            if (hasNickName) {
                next();
            } else {
                //用户登陆了,但是没有用户信息 
                try {
                    //发请求获取用户信息以后在放行
                    await store.dispatch('getUserInfo');
                    next();
                } catch (error) {
                    //用户没有信息,还携带token发请求获取用户信息【失败】
                    //token【学生证失效了】
                    //token失效:本地清空数据、服务器的token通知服务器清除
                    await store.dispatch('logout');
                    //回到登录页,重新获取一个新的学生证
                    next('/login');
                }
            }
        }
    } else {
        //用户未登录||目前的判断都是放行.将来这里会'回手掏'增加一些判断
        //用户未登录:不能进入/trade、/pay、/paysuccess、/center、/center/myorder  /center/teamorder
        let toPath = to.path;
        if (toPath.indexOf('trade') != -1 || toPath.indexOf('pay') != -1 || toPath.indexOf('center') != -1) {
        	// 先跳往login页进行登陆,将未登录前的路径存在路由中,发送至登录页面
            next('/login?redirect='+toPath);
        } else {
            next();
        }
    }
});

1.全局前置路由守卫

关于未登录的地址拦截\跳转
例如,未登录时不能去往个人中心,如果点击去往个人中心,全局前置路由守卫判断用户未登录,携带目标地址跳往login页面,登录成功后才能自动跳往目标页面

//用户未登录||目前的判断都是放行.将来这里会'回手掏'增加一些判断
        //用户未登录:不能进入/trade、/pay、/paysuccess、/center、/center/myorder  /center/teamorder
        let toPath = to.path;
        if (toPath.indexOf('trade') != -1 || toPath.indexOf('pay') != -1 || toPath.indexOf('center') != -1) {
            // 先跳往login页进行登陆,将未登录前的路径存在路由中
            next('/login?redirect='+toPath);
        } else {
            next();
        }
//在发登录请求
      try {
        //登录成功
        await this.$store.dispatch("userLogin", { phone, password });
//      若地址栏中有redirect参数,则跳往该地址
        let goPath = this.$route.query.redirect||'/home';
        //跳转到首页
        this.$router.push(goPath);
      } catch (error) {
        alert(error.message);
      }

2.独享路由守卫

在路由配置处配置

3.组件内路由守卫

beforeRouterEnter 在渲染该组件的对应路由被confirm之前调用
beforeRouterUpdate 路由发生改变 动态参数
beforeRouterLeave

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值