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>

    

     

三、总结                                                                       

猜你喜欢

转载自www.cnblogs.com/xxm980617/p/10848780.html