• Vue项目流程6,登录与注册,完成获取验证码,登录跳转,利用token获取用户信息,退出登录等功能,利用导航守卫在路由跳转之间进行判断


    登录与注册(重要)

    静态组件

    • assets文件夹:放置全部组件共用静态资源
    • 在样式中也可以使用@符号【src别名】,切记要在前面加一个~

    注册页面

    获取验证码

    1、写接口

    //获取验证码   地址:/api/user/passport/sendCode/{phone}   请求方法:GET   参数:需要
    export const reqGetCode = (phone)=> requests({url:`/user/passport/sendCode/${phone}`,method:'GET'})
    
    • 1
    • 2

    2、vuex三连环

    import { reqGetCode } from "@/api"
    //登录与注册的模块
    const state = {
        code:''
    }
    const mutations = {
        GETCODE(state,code){
            state.code = code
        }
    }
    const actions = {
        //获取验证码
        async getCode({commit},phone){
            let result = await reqGetCode(phone)
            if(result.code == 200){
                commit('GETCODE',result.data)
                return 'ok'
            }else{
                return Promise.reject(new Error('faile'))
            }
        }
    }
    const getters = {}
    export default {
        state,
        mutations,
        actions,
        getters
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    获取验证码的这个接口,把验证码返回,但是正常情况后台把验证码发到用户手机上
    3、点击事件

    async getCode(){
              try {
                const{phone} = this
                phone && (await this.$store.dispatch('getCode',phone))
                //验证码直接填写到框内
                this.code = this.$store.state.user.code
              } catch (error) {
                alert(error.message)
              }
            },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    完成注册

    1、接口

    //注册  地址:/api/user/passport/register  请求方式:POST  参数:phone code password
    export const reqUserRegister = (data)=> requests({url:'/user/passport/register',data,method:'POST'})
    
    • 1
    • 2

    2、actions

        //用户注册,未返回数据
        async userRegister({ commit }, user) {
            let result = await reqUserRegister(user)
            if (result.code) {
                return 'ok'
            } else {
                return Promise.reject(new Error('faile'))
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、点击事件

        //用户注册
        async userRegister() {
          try {
            const { phone, code, password, password1 } = this;
            phone &&
              code &&
              password == password1 &&
              (await this.$store.dispatch("userRegister", {
                phone,
                code,
                password,
              }));
              this.$router.push('/login')
          } catch (error) {
            alert(error.message);
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    登录页面

    登录跳转

    1、收集表单数据
    2、接口

    //登录  地址:/api/user/passport/login  请求方式:POST  参数:phone password
    export const reqUserLogin = (data)=> requests({url:'/user/passport/login',data,method:'POST'})
    
    • 1
    • 2

    2、vuex

    //登录业务[token]
    async userLogin({ commit }, data) {
        let result = await reqUserLogin(data)
        //服务器下发的token是用户的唯一标识
        if (result.code == 200) {
            commit('USERLOGIN', result.data.token)
            return 'ok'
        } else {
            return Promise.reject(new Error('faile'))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    登录成功时,后台为了区分这个用户是谁,服务器会下发token【令牌:唯一标识】,一般会持久化存储token,再带着token找服务器要用的信息进行展示。
    注意:vuex仓库存储数据不是持久化

    3、点击事件

    <button class="btn" @click.prevent="userLogin">  button>
    
    • 1

    取消表单的默认行为

    //用户登录
    async userLogin() {
      try {
        const { phone, password } = this;
        phone &&
          password &&
          (await this.$store.dispatch("userLogin", { phone, password }));
        this.$router.push("/home");
      } catch (error) {
        alert(error.message);
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    token获取用户信息

    1、接口

    //携带token获取用户的信息  地址:/api/user/passport/auth/getUserInfo  请求方式:GET
    export const reqUserInfo = ()=> requests({url:'/user/passport/auth/getUserInfo',method:'GET'})
    
    • 1
    • 2

    2、在请求拦截器中在请求头携带token

    //判断需要携带token
    if(store.state.user.token){
        config.headers.token = store.state.user.token
    }
    
    • 1
    • 2
    • 3
    • 4

    3、vuex

        //获取用户信息
        async getUserInfo({commit}){
            let result = await reqUserInfo()
            if(result.code == 200){
                commit('GETUSERINFO',result.data)
                return 'ok'
            }else{
                return Promise.reject(new Error('faile'))
            }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、在TheHome组件挂载完毕之后派发action

    //获取用户信息在首页展示
        this.$store.dispatch('getUserInfo',this.token)
    
    • 1
    • 2

    5、在TheHeader组件展示数据

    computed:{
        userName(){
            return this.$store.state.user.userInfo.name
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    <p v-if="!userName">
    	<span>span>
        
    	<router-link to="/login">登录router-link>
        <router-link to="/register" class="register">免费注册router-link>
    p>
    <p v-else>
    	<a>{{userName}}a>
        <a class="register">退出登录a>
    p>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    6、当获取到token时持久化存储token

    export const setToken = (token)=> {
        localStorage.setItem('TOKEN',token) 
    }
    export const getToken = ()=> {
        return localStorage.getItem('TOKEN') 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    获得之后本地存储

    setToken(result.data.token) 
    
    • 1

    state中获得

    token:getToken(),
    
    • 1

    逻辑:
    当未发起请求时,state中的token无法在本地中找到,即为null。当第一次发起请求即登录成功之后,token就已经本地存储了,当再次刷新时state中的token可以获得本地存储的token,所以再次刷新仍有token。

    退出登录

    1、接口

    //退出登录  地址:/api/user/passport/logout  请求方式:GET
    export const reqLogout = ()=> requests({url:'/user/passport/logout',method:'GET'})
    
    • 1
    • 2

    2、actions

    //退出登录
    async userLogout({commit}){
        let result = await reqLogout()
        if(result.code == 200){
            //action中不能操作state
            commit('CLEAR')
            return'ok'
        }else{
            return Promise.reject(new Error('faile'))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    3、mutations

    export const removeToken = ()=> {
        localStorage.removeItem('TOKEN')
    }
    
    • 1
    • 2
    • 3
        CLEAR(state){
            state.token = ''
            state.userInfo = {}
            removeToken()
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4、点击事件

    //退出登录
    async logout(){
        //1、发请求
        //2、清除项目当中的数据【userInfo/token】
        try {
            await this.$store.dispatch('userLogout')
            //回到首页
            this.$router.push('/home')
        } catch (error) {
            alert(error.message)
        } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    导航守卫

    全局守卫:项目中,只要发生路由的变化,守卫就能监听到

    //全局守卫:前置守卫(在路由跳转之间进行判断)
    router.beforeEach(async(to,from,next)=>{
        //to:跳转到哪一个组件
        //from:从哪个路由来
        //next:放行函数 next()   next('/login')放行到指定路由   next(false)
        let token = store.state.user.token
        let name = store.state.user.name
        if(token){
            if(to.path == '/login'){
                next('/')
            }else{
                //登录了,去的不是login
                if(name){
                    next()
                }else{
                    //没有用户信息,派发action
                    try {
                        //获取成功
                        await store.dispatch('getUserInfo')
                        next()
                    } catch (error) {
                        //token失效了
                        await store.dispatch('userLogout')
                        next('/login')
                    } 
                }  
            }
        }else{
            next()
        }
    })
    export default router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    TheHome组件派发的获取用户信息action删掉

  • 相关阅读:
    Vue 禁止输入框输入空格
    一文教你快速搭建数据驱动自动化测试框架
    CSS 属性学习笔记(入门)
    常见的传输介质及其特性
    小黑子—Maven基础
    力扣(LeetCode)180. 连续出现的数字(2022.06.29)
    飞天使-学以致用-devops知识点4-SpringBoot项目CICD实现(实验失败,了解大概流程)
    数论合集
    【英语小作文】-相关
    seata处理分布式事务
  • 原文地址:https://blog.csdn.net/qq_49080239/article/details/126563366