• Web项目 - 登录注册业务逻辑


    注册业务

    登录注册业务

    • 对于企业当中,一般项目都有登录注册功能【这个业务很重要】
    • 当然有一些项目不需要注册,后台管理系统项目,一般不需要注册

    在尚品汇项目中

    • 登录与注册的静态组件(图片问题会报错) 我们需要修改项目中图片的路径等

    assets【放置静态资源文件的地方】

    • 一般放置所有组件共用的静态资源
    • 在样式当中也可以使用@,在样式当中使用@,前面加上~

    注册的业务

    获取验证码

    • 在做注册、登录业务的时候,先不处理表单的验证功能,在项目最后一天,在把表单如何验证,如果是那哪些插件解决【最后去处理】 正则表达式
    • 手机号、验证码、密码需要满足的规则

    手机号:11
    验证码:4-6
    登录密码|确认密码:首字母大写、包含英文、数字、特殊字符等等。

    获取验证码接口

    /api/user/passport/sendCode/{phone} 
    
    • 1

    有接口的话,都是一样的,现在api文件夹下的index.js书写方法,调用接口等

    // 获取商品验证码 /api/user/passport/sendCode/{phone} method: 'get'
    export const reqGetCode = (phone) => requests({
        url: `/user/passport/sendCode/${phone}`,
        method: 'get',
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    **在注册组件中我们需要实时获取到用户输入的手机号和服务器返回的验证码,所以我们需要使用到 ** v-model 来处理

    同样的,除了手机号和验证码,密码和确认密码,以及是否同意都需要在data中设置定义

    data() {
        return {
          // 收集表单数据 -- 手机号
          phone: "",
          // 验证码
          code: "",
          // 密码
          password: "",
          // 确认密码
          password1: "",
          // 是否同意
          agree: true,
        };
      },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    // 实时获取手机号
    
    // 获取到了验证码在input框实时展示
    
    
    • 1
    • 2
    • 3
    • 4

    书写完接口以后,我们要做的就是去store文件夹下书写vuex三连环 – 用户的登录注册业务逻辑重新用一个user文件夹
    在这里插入图片描述

    • 我们要获取验证码,验证码是否获取成功,使用async & await 来书写
    • 下面要做的就是通过验证码的接口,把验证码返回,
    • 但是在正常正常情况下,后台把验证码发到用户手机上 [省钱]
    • 如果真是后台处理好了,下面就不用执行commit操作,用户看完会自己进行输入操作
    // 和之前的套路其实是一样的操作 我们一般都是在仓库中发请求
    import { reqGetCode } from "@/api"
    import { setToken, getToken, removeToken } from "@/utils/token"
    // 登录与注册的模块
    const state = {
        code: ' ',
    }
    
    const mutations = {
        GETCODE(state, code) {
            state.code = code.data
        }
    }
    
    const actions = {
        // 获取验证码
        async getCode({ commit }, phone) {
            /* 
                获取验证码的这个接口,把验证码返回,但是正常情况下,后台把验证码发到用户手机上[省钱]
                - 如果真是后台处理好了,下面就不用执行commit操作,用户看完会自己进行输入操作
            */
            let result = await reqGetCode(phone)
            // console.log(result)
            if (result.status == 200) {
                commit('GETCODE', result.data)
                return 'OK'
            } else {
                return Promise.reject(new Error('fail'))
            }
        },
    
    • 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

    书写了actions以后需要在Register组件中进行相应的派发

    Register组件的书写

    • 获取验证码同样需要用到 async & await 以及 try & catch的使用
    • 一个很重要的操作就是,拿到验证码以后,需要将验证码展示到页面当中 this.code = this.$store.state.user.code;
    methods: {
        // $store.dispatch('getCode', phone)
        // 获取验证码
        async getCode() {
          try {
            // 简单判断一下 -- 至少要有数据
            const { phone } = this;
            phone && (await this.$store.dispatch("getCode", phone));
            // this.$store.dispatch('getCode', this.phone)
            // 如果获取到验证码:将组件的code属性变为仓库中的验证码,进行展示
            // 验证码直接自己填写了
            // console.log(this.$store);
            // console.log(this.$store.state.user.code);
            this.code = this.$store.state.user.code;
          } catch (error) {
            alert(error.message)
          }
        },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    用户注册

    用户注册的接口 method:‘post’

    url:/api/user/passport/register 
    
    • 1

    书写调用接口方法

    • 该方法中需要传入很多参数数据如:phone、code、password 等,我们可以存在一个data对象中,后面用解构赋值操作
    // 注册的接口 
    // url:/api/user/passport/register method:post  phone code password(带的东西太多了,可以放到一个对象当中)
    export const reqUserRegister = (data) => requests({
        url: '/user/passport/register',
        data,
        method: 'post'
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    书写接口以后,在vuex中使用该接口,注册成功以后也不需要返回数据,不需要书写三连环

    // 用户注册, 派发action, 然后进行发送请求的操作 
    // 也因为不需要返回数据,所以不需要接着上面书写三连环了
    async userRegister({ commit }, user) {
        let result = await reqUserRegister(user)
        // console.log(result)
        if (result.status == 200) {
            return 'ok'
        } else {
            return Promise.reject(new Error('fail'))
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    同样需要在Register组件中派发该actions才行

    • 在用户进行注册的时候,需要满足的用户逻辑是 ① 用户输入的电话号码存在 ② 验证码输入存在 ③ 输入密码和确认密码同
    • 还有就是注册成功以后,需要进行跳转,跳转到登录操作页面
    // 用户注册
    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

    用户登录

    当你点击登录按钮的时候,需要把手机号、密码需要携带给服务器,服务器需要判断,你是不是我的用户【注册过的】
    如果是用户登录成功,进行登录,如果用户登录失败给一个提示即可。

    登录接口 - 接口书写完了以后,需要去仓库中发送请求,这一点很关键

    • 携带的数据很多的情况下,解决方法一般都是使用一个data参数,在传入参数的时候,进行相应的解构赋值即可
    url:'/api/user/passport/login' method:post  phone password 
    
    • 1
    • 书写接口函数
    export const reqUserLogin = (data) => requests({
        url: '/user/passport/login',
        data,
        method: 'post'
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    token

    • 【令牌:字符串,服务器下发给用户的身份凭证】
    • 举例子:古代大战,兵符

    登录业务的时候,我们需要明白是否登录成功,我们也是用async|await进行书写,

    • 用户登录一定是需要携带token,将来我们需要利用该token来唯一标识一个用户,携带token来获取用户信息的

    书写token.js来对token进行存储和获取操作 -一般放在utils工具包下面
    在这里插入图片描述

    // 因为是进行本次存储操作,所以对外暴露一个函数即可
    // 对外暴露一个函数
    // 存储TOKEN
    export const setToken = (token) => {
        localStorage.setItem('TOEKN', token)
    }
    
    // 获取TOKEN
    export const getToken = () => {
        localStorage.getItem('TOKEN')
    }
    
    // 删除token
    export const removeToken = () => {
        localStorage.removeItem('TOKEN')
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    书写登录业务 - 用户登录以后需要将token信息传入到state中

    const state = {
        code: '',
        // token: '',
        // token: localStorage.getItem('TOEKN'), // 其实状态下,就算是没存,相当于null值,但是在下一次刷新的时候就存了
        token: getToken(),
    }
    const mutations = {
        USERLOGIN(state, token) {
            state.token = token
        },
    }
    // 登录业务[token]
    const actions = {
    	async userLogin({ commit }, data) {
    	    // 需要的就是等待他成功的结果等 操作,这一点很关键 返回的结果就是登录成功或者是失败等
    	    let result = await reqUserLogin(data)
    	    // console.log(result)
    	    // 服务器下发token,用户唯一标识符(uuid)
    	    // 将来经常通过带token找服务器要用户信息进行相应展示
    	    if (result.status == 200) {
    	        // 用户已经登录成功且获取到了token
    	        commit('USERLOGIN', result.data.data.token)
    	        // 持久化存储token,因为token本身就是字符串的形式,所以不用转换
    	        // localStorage.setItem('TOEKN', result.data.data.token)
    	        setToken(result.data.data.token)
    	        return 'ok'
    	    } else {
    	        return Promise.reject(new Error('fail'))
    	    }
    	},
    }
    
    • 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

    在Login登录组件中派发actions

    • 在login组件中,我们也需要获取用户输入的phone和code,同样是使用v-model来进行操作
    • 在进行派发之前也做一个简单的判断,判断用户输入的phone和code是否存在
    • 登录成功以后,用户需要跳转到首页
    // 登录的回调
    async userLogin() {
      try {
        // alert(123) 同样的,在进行登录之前要拿到相应的东西 需要注意的一点就是vuex存储的数据不是持久化的
        const { phone, password } = this;
        (await this.$store.dispatch("userLogin", { phone, password })) && (phone && password)
        // 登录成功 - 跳转到home首页
        this.$router.push('/home')
      } catch (error) {
        alert(error.message)
      }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    获取用户信息【需要带着用户的token向服务器要用户信息】

    重要问题
    1、为什么刷新页面,用户信息就消失?

    • 用户刷新页面,用户信息消失没了获取不到,因为token没有携带给服务器【需要在请求拦截器的标头添加上token字段】。
    • Vuex存储数据是否持持久化的?并非持久化, 本地存储持久化存储token

    获取用户信息接口

    URL:api/user/passport/auth/getUserInfo  method: get
    
    • 1
    // 需要对接口操作的话,都是需要书写相应的方法的
    // 获取用户信息【需要带着用户的token向服务器要用户信息】 
    // 没有参数的话还是使用请求头来进行携带操作
    // URL:api/user/passport/auth/getUserInfo  method: get
    export const reqUserInfo = () => requests({
        url: 'user/passport/auth/getUserInfo',
        method: 'get'
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我们需要在请求拦截器中,在请求头上面带上我们的token字段, - header上添加的字段不能是乱写的,应该和后台老师商量好

    // 请求拦截器,在发请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情 请求拦截器在发送请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情,
    requests.interceptors.request.use((config) => {
        // console.log(store)
        if(store.state.detail.uuid_token){
            // 给请求头添加一个字段 和后台老师商量好了  userTempId 不能瞎写
            config.headers.userTempId = store.state.detail.uuid_token
        }
        // 需要携带token带给服务器
        if(store.state.user.token) {
            // console.log('@@@')
            config.headers.token = store.state.user.token
        }
        // 进度条开始动
        nProgress.start()
        // 请求拦截器中就算什么都不做的话,也需要返回一个配置对象,要不然会报错,config中包含headers
        return config
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在actions中调用接口,获取用户信息

    // 获取用户登录信息 
    /* async getUserInfo({commit}) {
        let result = await reqUserInfo() // 没有什么参数,发送请求的操作,应该在home组件中完成
        // console.log(result) 
        if(result.status == 200) {
            // 提交用户信息
            commit('GETUSERINFO', result.data)
            // 捞取用户信息,成功也可以,失败也可以
            return 'ok'
        }else {
            return Promise.reject(new Error('fail'))
        }
    } */
    async getUserInfo({ commit }) {
        let result = await reqUserInfo() // 没有什么参数,发送请求的操作,应该在home组件中完成
        console.log(result)
        if (result.status == 200) {
            // 提交用户信息
            commit('GETUSERINFO', result.data.data)
            // 捞取用户信息,成功也可以,失败也可以
        }
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    用于登录操作会获取相应的信息,需要在mutations中进行展示

    const state = {
        userInfo: {}
    }
    const mutations = {
        GETUSERINFO(state, userInfo) {
            state.userInfo = userInfo
        },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    因为获取的用户信息是用户名等,在Home组件中进行展示,所以我们需要在Home组件中派发actions

    this.$store.dispatch('getUserInfo')
    
    • 1

    最后我们需要在header组件中,显示用户信息
    在这里插入图片描述
    在组件中有用户名的时候显示一种状态,没有用户名的时候,显示另一种状态 使用 v-if & v-else

     <!-- 没有用户的时候,进行显示即可 -->
    <p v-if="!userName">
      <span></span>
      <router-link href="###" to="/login">登录</router-link>
      <router-link href="###" class="register" to="/register"
        >免费注册</router-link
      >
    </p>
    <!-- 登录了 -->
    <p v-else>
      <a>{{ userName }}</a>
      <a class="register" @click="logout">退出登录</a>
    </p>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 登录成功以后的状态

    在这里插入图片描述

    退出登录操作

    1. 发请求,需要通知服务器,把现在用户身份token【销毁】
    2. 清除仓库数据+本地存储数据【都需要清理】

    退出登录接口

    /api/user/passport/logout
    
    • 1

    书写接口方法

    // 退出登录 /api/user/passport/logout
    export const reqLogout = () => requests({
        url:'/user/passport/logout', 
        method:'get'
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    vuex中书写actions

    // 退出登录
    async userLogout({commit}) {
        // 只是向服务器发起一次请求,通知服务器清楚token
        let result = await reqLogout()
        // 还需要清楚本地的一些内容
        // 注意 action中不能操作state,我们必须提交到mutation修改state
        if (result.status == 200) {
            commit('CLEAR')
            return 'ok'
        } else {
            return Promise.reject(new Error('fail'))
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    退出登录以后,我们需要对服务器中的数据进行相应的操作修改 mutations

    const mutations = {
        CLEAR(state) {
            // 删除用户信息
            state.token = ''
            state.userInfo = {}
            // 还需要清空本地存储的一些内容 token
            removeToken()
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后在Header组件中点击退出登录,派发actions

    <a class="register" @click="logout">退出登录</a>
    
    • 1
    // 退出登录
    async logout() {
      // 退出登录,需要做的事情
      // 1、需要发请求,通知服务器退出登录【清除一些数据:token】
      //  服务器肯定需要返回成功或者失败,尤其是删除成功以后还需要回到首页的操作
      try {
        await this.$store.dispatch("userLogout");
        // 如果退出成功,回到首页
        this.$router.push('/home')
      } catch (error) {
        alert(error.message);
      }
      // 2、清除项目当中的数据【userInfo、token】 因为下一次用户登录就是在此处
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 而且退出成功以后,我们也是需要回到首页的
  • 相关阅读:
    leetcode 122. 买卖股票的最佳时机 II
    Flask-SQLAlchemy 快速上手
    阿里云视频点播+项目实战
    Python爬虫爬取豆瓣电影短评(爬虫入门,Scrapy框架,Xpath解析网站,jieba分词)
    基于传统Session的登录
    redis双写一致性,缓存更新策略,缓存穿透,缓存击穿,缓存雪崩
    【Head First Java 笔记】参数传递
    Pytest 参数参考
    innodb_ruby 视角下 MySQL 记录增删改
    当前JavaEE初阶的阶段知识总结
  • 原文地址:https://blog.csdn.net/A13526_/article/details/126286805