1. 程式人生 > >Vue(vue+node.js+mongodb)_登錄註冊(密碼登錄)

Vue(vue+node.js+mongodb)_登錄註冊(密碼登錄)

export rec keys ring vuex err 技術分享 resp 內容

一、前言

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>

三、總結

Vue(vue+node.js+mongodb)_登錄註冊(密碼登錄)