• Vue(vue+node.js+mongodb)_登录注册(密码登录)


    一、前言                                                                       

     1、密码登录(分析)

    2、验证码部分

    3、提交表单

    4、保存显示

    5、完善功能,首页中如果登录成功之后显示的是图标,没有登录显示的是“注册登录”

    6、处理bug(当我们一刷新之后当前登录的信息都没有了)

    二、主要内容                                                                

    1、密码登录(分析)

           

        (1)第一步用户输入先提交登录表单信息

        

            

    2、验证码部分

    这里显示的验证码,在通过异步调用获取到,并且在后端存进session中

    (1)前端部分

    <!--获取验证码:前端-->
     <input type="text" maxlength="11" placeholder="验证码" v-model="captcha">
     <img class="get_verification" src="http://localhost:4000/captcha" alt="captcha"  @click="getCaptcha" ref="captcha">

    (2)每次点击的时候获取一个新的图片验证码

     // 获取一个新的图片验证码
          getCaptcha () {
            // 每次指定的src要不一样
            this.$refs.captcha.src = 'http://localhost:4000/captcha?time='+Date.now()
          }

    (3)发送http://localhost:4000/captcha请求的时候,后台接受到这个请求,并且将当前的这个保存到session中

    /*
    一次性图形验证码
     */
    router.get('/captcha', function (req, res) {
      var captcha = svgCaptcha.create({
        ignoreChars: '0o1l',
        noise: 2,
        color: true
      });
      req.session.captcha = captcha.text.toLowerCase();//将创建的这个新的验证码保存到session中
      console.log(req.session.captcha)
      /*res.type('svg');
      res.status(200).send(captcha.data);*/
      res.type('svg');
      res.send(captcha.data)
    });

    3、提交表单

          (1)提交表单的时候触发login()方法,然后调用自己在api/index.js中封装的axios方法

     async login () {
            let result
         
            // 密码登陆
              const {name, pwd, captcha} = this
              if(!this.name) {
                // 用户名必须指定
                this.showAlert('用户名必须指定')
                return
              } else if(!this.pwd) {
                // 密码必须指定
                this.showAlert('密码必须指定')
                return
              } else if(!this.captcha) {
                // 验证码必须指定
                this.showAlert('验证码必须指定')
                return
              }
              // 发送ajax请求密码登陆
              result = await reqPwdLogin({name, pwd, captcha})
            
    }

          (2)reqPwdLogin方法如下

                   封装的ajax

    import axios from 'axios'
    export default function ajax(url = '', data = {}, type = 'GET') {
            return new Promise(function (resolve, reject) {
            let promise
            if (type === 'GET') {
            // 准备url query 参数数据
            let dataStr = '' //数据拼接字符串
            Object.keys(data).forEach(key => {
            dataStr += key + '=' + data[key] + '&'
            })
            if (dataStr !== '') {
            dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
            url = url + '?' + dataStr
            }
            // 发送get 请求
            promise = axios.get(url)
            } else {
            // 发送post 请求
            promise = axios.post(url, data)
            }
            promise.then(response => {
            resolve(response.data)
            })
            .catch(error => {
            reject(error)
            })
            })
    }
    ajax.js

                  

    import ajax from './ajax'
    const BASE_URL = '/api'
    //5.根据用户名密码登录
    export const reqPwdLogin = ({name, pwd, captcha}) => ajax('/api'+'/login_pwd', {name, pwd, captcha}, 'POST')

           (3)执行完第三步之后,会向服务器发送请求,服务器处理post请求

    /*
    密码登陆
     */
    router.post('/login_pwd', function (req, res) {
      const name = req.body.name   //将表单提交的数据存下来
      const pwd = md5(req.body.pwd)
      const captcha = req.body.captcha.toLowerCase()
      console.log('/login_pwd', name, pwd, captcha, req.session)
    
      // 可以对用户名/密码格式进行检查, 如果非法, 返回提示信息
      if(captcha!==req.session.captcha) {
        return res.send({code: 1, msg: '验证码不正确'})
      }
      // 删除之前保存的验证码
      delete req.session.captcha
    
      UserModel.findOne({name}, function (err, user) {
        if (user) {
          console.log('findUser', user)
          if (user.pwd !== pwd) {
            res.send({code: 1, msg: '用户名或密码不正确!'})
          } else {
            req.session.userid = user._id 
            res.send({code: 0, data: {_id: user._id, name: user.name, phone: user.phone}})
          }
        } else {
          const userModel = new UserModel({name, pwd})
          userModel.save(function (err, user) {
            // 向浏览器端返回cookie(key=value)
            // res.cookie('userid', user._id, {maxAge: 1000*60*60*24*7})
            req.session.userid = user._id
            const data = {_id: user._id, name: user.name}
            // 3.2. 返回数据(新的user)
            res.send({code: 0, data})
          })
        }
      })
    })

      (4)后台验证成功后需要做两步操作

            第一步:将后台返回的user信息保存在vuex的state中去

            第二步:实现路由跳转

     async login () {
            let result
           // 密码登陆
              const {name, pwd, captcha} = this
              if(!this.name) {
                // 用户名必须指定
                this.showAlert('用户名必须指定')
                return
              } else if(!this.pwd) {
                // 密码必须指定
                this.showAlert('密码必须指定')
                return
              } else if(!this.captcha) {
                // 验证码必须指定
                this.showAlert('验证码必须指定')
                return
              }
              // 发送ajax请求密码登陆
              result = await reqPwdLogin({name, pwd, captcha})
            
            // 停止计时
            if(this.computeTime) {
              this.computeTime = 0
              clearInterval(this.intervalId)
              this.intervalId = undefined
            }
    
            // 根据结果数据处理
            if(result.code===0) {
              const user = result.data
              // 将user保存到vuex的state
              this.$store.dispatch('recordUser', user)
              // 去个人中心界面
              this.$router.replace('/profile')
            } else {
              // 显示新的图片验证码
              this.getCaptcha()
              // 显示警告提示
              const msg = result.msg
              this.showAlert(msg)
            }
          }

    4、保存显示

      (1)用vuex来管理状态

        

        state.js中定义userinfo来存放提交成功的用户名和密码

    export default{
        
        userInfo:{}//保存提交的用户信息
    }

         mutation-types.js中定义

    export const RECEIVE_USER_INFO = 'receive_user_info'//接受用户信息

         mutations.js

    /*
    vuex的mutations.js模块
    */
    import {
          RECEIVE_USER_INFO,
    } from './mutation-types'
    export default{
        //这个是方法名,action 和mutation交互的时候传的是包含这个数据的对象
          [RECEIVE_USER_INFO] (state, {userInfo}){
                state.userInfo = userInfo
          }
    }

         actions.js

    /*
    vuex的actions.js模块
    */
    import {    
        RECEIVE_USER_INFO,    
    } from './mutation-types'
    
    //三个接口函数
    import {    
        reqUserInfo,
    
    } from '../api'
    
    export default{
        //同步记录用户信息
        recordUser ({commit},userInfo){
            commit(RECEIVE_USER_INFO,{userInfo})       
        },
    }

    (2)在app.vue中用,模块actions中记录的保存用户信息事件,

    // 根据结果数据处理
            if(result.code===0) {
              const user = result.data
              // 将user保存到vuex的state
              this.$store.dispatch('recordUser', user)
              // 去个人中心界面
              this.$router.replace('/profile')
            } else {
              // 显示新的图片验证码
              this.getCaptcha()
              // 显示警告提示
              const msg = result.msg
              this.showAlert(msg)
            }

    (3)登录成功之后显示用户名,实现如下效果

         第一步:需要从state中取出保存的userInfo,然后显示在页面中

    import {mapState} from 'vuex'
        export default{
           components:{
               HeaderTop
           },
    
           computed:{
               ...mapState(['userInfo'])
           }
          
        }
    </script>

        第二步:显示

    <!--如果有userInfo信息,这里就显示用户信息,否则就显示注册/登录-->
    <p class="user-info-top">{{userInfo._id|| '注册|登录'}}</p>

    5、完善功能,首页中如果登录成功之后显示的是图标,没有登录显示的是“注册登录”

         (1)已登录

         (2)未登录

    <router-link class="header_login" slot='right' :to="userInfo._id? '/userInfo':'/login'">
                       <span class="header_login_text" v-if="!userInfo._id">登录注册</span>
                       <span class="header_login_text" v-else>
                             <i class="iconfont icon-geren"></i>
                       </span>
    </router-link>

    6、处理bug(当我们一刷新之后当前登录的信息都没有了)

            session是以赖与cookie的,

            一般有两种cookie,一种是会话级别的(当刷新浏览器,或者关闭浏览器之后,在cookie中保存的信息就没有了),一种是持久化的(可以在cookie中将信息保存一段时间)

    (1)在后台中设置保存的时间

    app.use(session({
      secret: '12345',
      cookie: {maxAge: 1000*60*60*24 },  //设置maxAge是80000ms,即80s后session和相应的cookie失效过期
      resave: false,
      saveUninitialized: true,
    }));

    (2)服务器中会根据session中的userid,查询对应的user

    /*
    根据sesion中的userid, 查询对应的user
     */
    router.get('/userinfo', function (req, res) {
      // 取出userid
      const userid = req.session.userid
      // 查询
      UserModel.findOne({_id: userid}, _filter, function (err, user) {
        // 如果没有, 返回错误提示
        if (!user) {
          // 清除浏览器保存的userid的cookie
          delete req.session.userid
    
          res.send({code: 1, msg: '请先登陆'})
        } else {
          // 如果有, 返回user
          res.send({code: 0, data: user})
        }
      })
    })

        (3)前台最开始肯定要向后台发送一个请求,如果查询到了,当前的用户信息是session中保存的信息,就免登陆

    在actions.js模块中添加一个方法

    //异步获取用户信息,让应用一开始就调用这个方法
        //获取商家列表
        async getUserInfo ({commit, state}){
            //1.发送异步ajax请求,调用上面那个方法,现在的数据是在state里面
            const result = await reqUserInfo()
            //2.提交一个mutation
            if(result.code == 0){
                const userInfo = result.data
                commit(RECEIVE_USER_INFO,{userInfo:result.data})
            }
        }

       (4)在前台调用这个方法

    <script>
      import FooterGuide from './components/FooterGuide/FooterGuide.vue'
      import {mapActions} from 'vuex'
    export default {
      name: 'App',
      components:{
        FooterGuide
      },  
      mounted(){ 
       this.getUserInfo()
      }
      ,
      methods:{
        ...mapActions(['getUserInfo'])
      }
    }
    </script>

        

         

    三、总结                                                                       

    虽然现在走得很慢,但不会一直这么慢
  • 相关阅读:
    浏览器渲染
    微信h5页面制作总结
    chrome开发工具指南之综述
    零碎记录
    docker 容器已经启动,但是无法访问
    Docker的安装及使用
    python目录选择
    centos7 设置进程开机自启动
    语句中传入变量
    kafka -> structuredStreaming读取kafka日志 ->自定义输出到mysql
  • 原文地址:https://www.cnblogs.com/xxm980617/p/10848780.html
Copyright © 2020-2023  润新知