【Vue.js】vue用户登录功能
之前用vue實現一個網站的登錄功能,這里做一個記錄和總結,以下是需要實現的登錄業務描述:
1.輸入用戶名和密碼,點擊登錄按鈕,若兩者匹配,即可進入首頁,首頁展示登錄用戶的信息;
2.當用戶登錄后,無法訪問登錄頁;
3.用戶未登錄,無法訪問需要登錄才能展示的頁面,此時需要跳轉到登錄頁面,當登錄成功后,直接跳轉到剛才用戶點擊訪問的頁面。
一.基本的登錄功能實現
首先簡單介紹登錄的邏輯,順序圖如下:
登錄按鈕綁定點擊事件handleLogin,先要做前端驗證,就是檢查用戶名和密碼的規范性,可以按照需求具體問題具體分析,比如做正則判斷,或者發送請求驗證是否存在等,這里不詳細實現了,僅判斷用戶是否輸入,之后派發vuex,action為userLogin,login.vue的主要代碼如下:
data(){return {phone:'',password:''}}, async handleLogin(){const {phone,password} = this;try {phone && password && await this.$store.dispatch('userLogin',{phone,password});let toPath = this.$route.query.redirect || 'home';this.$router.push(toPath);} catch (error) {alert(error.message);} }在userLogin里,調用封裝好的reqLogin方法向后端接口發送登錄請求,該請求的響應結果為兩種類型,如果用戶名和密碼正確,返回token(驗證用戶信息的字符串),若登錄失敗,返回失敗的原因。
這里使用async和await修飾符處理異步請求,async修飾的方法userLogin會返回一個Promise實例,這里可以通過userLogin返回的Promise是成功或失敗告知login.vue組件登錄行為的結果。當登錄成功時,首先讓vuex保存token,但是vuex數據刷新后會丟失,所以還需要將token信息保存在瀏覽器的本地存儲中,返回一個非Promise的類型。登錄失敗,返回一個失敗的Promise,并將失敗的原因作為異常拋出。
隨后在登錄組件login.vue中,判斷userLogin的返回結果,由于使用到了await修飾符處理異步操作,且它只能獲取到成功的Promise,所以這里使用try...catch...獲取await的失敗結果,當登錄失敗時將原因彈出在頁面上。
成功后使用$router.push(toPath),跳轉至home首頁。
vuex代碼:
import {reqGetCode,reqRegister,reqLogin,reqUserInfo,reqUserLogout} from '@/api' const state = {code:'',// vue倉庫存儲數據不是持久化的,刷新數據丟失token:localStorage.getItem('TOKEN') || '',userInfo:{} }; const mutations = {USERLOGIN(state,token){state.token = token;},USERINFO(state,userInfo){state.userInfo = userInfo || {};}, }; const actions = {async userLogin(context,data){// 發送登錄請求let result = await reqLogin(data);if(result.code === 200) {// 存放token,vuex和localStorage各一份context.commit('USERLOGIN',result.data.token);localStorage.setItem('TOKEN',result.data.token);return 'ok';} else {// 登錄失敗return Promise.reject(new Error(result.message));}}, }token即令牌,是服務器識別登錄用戶信息的有效憑證,在登錄成功時由服務器返回前端,它一般存放在本地存儲中,并在登陸后的請求中放在請求頭中一起提交服務器,從而讓服務器驗證登錄用戶身份的合法性。當跳轉至首頁后,就需要發請求獲取用戶信息了,此時就需要將剛才獲取的token提交服務器了,需要對axios請求做二次封裝,如下:
import axios from 'axios' // 引入進度條 import nprogress from 'nprogress' // 引入進度條的樣式 import 'nprogress/nprogress.css' // 引入store import store from '@/store' // 創建axios實例 const requests = axios.create({// 配置對象// 基礎路徑baseURL:"/api",// 請求超時的時間timeout:5000, });// 請求攔截器 -- 在請求發出前做些事情 requests.interceptors.request.use((config) => {// 需要攜帶token給服務器if(store.state.user.token) {config.headers.token = store.state.user.token;}nprogress.start();// config 是配置對象,里面包含請求頭headersreturn config; });// 響應攔截器 requests.interceptors.response.use((res) => {nprogress.done();return res.data; },(err) => {return Promise.reject(new Error('fail')) });export default requests;核心就是在axios的請求攔截器中給登錄后的每次請求添加請求頭token:config.headers.token = store. state. user.token
在首頁發送請求
<template><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 href="#">{{userName}}</a><a href="#" class="register" @click="logout">退出登錄</a></p> </template><script> export default {name:"home",mounted(){this.getUserInfo();},computed:{userName(){let userInfo = this.$store.state.user.userInfo;return userInfo.name || '';}}methods:{getUserInfo(){try {await this.$store.dispatch('getUserInfo');} catch (error) {// alert(error.message);}}} } </script>vuex:
const state = {userInfo:{} }; const mutations = {USERINFO(state,userInfo){state.userInfo = userInfo || {};}, }; const actions = {// 獲取用戶信息(token)async getUserInfo(context){let result = await reqUserInfo();if(result.code === 200) {context.commit('USERINFO',result.data);return 'ok';} else {return Promise.reject(new Error(result.message));}}, }二.使用路由守衛做未登錄攔截
以上實現了基本登錄的功能,但依舊要進行一些優化,比如登錄后訪問登錄頁面需要跳轉,以及未登錄訪問用戶信息相關的頁面的攔截的功能,這里就需要使用到vue-router的路由全局守衛了,?全局守衛的配置一般實在路由配置文件中進行的,一般是項目中routes/index.js文件中。
需要做的就是在路由跳轉之前使用全局前置守衛router.beforeEach,對跳轉的頁面和登錄狀態做判斷,具體判斷的邏輯如下:
?routes/index.js:
import Vue from 'vue' import VueRouter from 'vue-router' import routes from './routes' import store from '@/store'// 使用路由插件 Vue.use(VueRouter); // 配置路由 const router = new VueRouter({// 配置路由routes,// 滾動行為scrollBehavior(to, from, savedPosition) {// return 期望滾動到哪個的位置// y:0代表垂直滾動條在最上方return {y:0};} }); // to:獲取到跳轉的那個路由信息; // from:獲取到哪個路由而來的信息; // next:放行函數, // next('/login'):放行到指定的路由 // next(false):返回到起始的路由 router.beforeEach(async (to,from,next) => {let token = store.state.user.token;if(token) {// 登錄if(to.path === '/login') {// 登陸后訪問登錄頁next({path:from.path});} else {// 登陸后訪問非登錄頁if(!store.state.user.userInfo.name) {// 當空對象作為判斷條件時,相當于true。當空對象與布爾值直接比較時,相當于true,但空數組與布爾值直接比較時是false// 登錄后訪問非登錄頁,如果此時用戶信息由于頁面刷新,store為空需要再次請求后端,拿到用戶信息try {await store.dispatch('getUserInfo');next();} catch (error) {// token過期await store.dispatch('userLogout');next({path:'/login'});}} else {// 登錄后訪問非登錄頁,無刷新操作next();}}} else {// 未登錄if(to.path.indexOf('/pay') ==! -1 || to.path.indexOf('trade') !== -1 || to.path.indexOf('center') !== -1) {next(`/login?redirect=${to.path}`); } else {next();}} });export default router;這里還需要注意一點,就是當用戶處于未登錄狀態下,點擊需要登錄才能訪問的頁面時,會跳轉登錄頁,但登錄成功后需要直接跳轉到剛剛點擊的那個頁面而不是首頁,所以這里在跳轉登陸頁時通過query傳參的方式,即:next(`/login?redirect=${to.path}`),將跳轉的路由路徑to.path傳遞給登錄頁,在成功登錄后使用編程式路由導航this.$router.push(this.$route.query.redirect)跳轉。
總結
以上是生活随笔為你收集整理的【Vue.js】vue用户登录功能的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【vue.js】vue后台项目权限功能实
- 下一篇: html5倒计时秒杀怎么做,vue 设