基于Vue.js實(shí)現(xiàn)一個(gè)完整的登錄功能
1. 引言
用戶登錄功能是Web應(yīng)用中最常見的功能之一。它通常包括表單輸入、數(shù)據(jù)驗(yàn)證、接口調(diào)用、狀態(tài)管理等多個(gè)步驟。在Vue.js中,我們可以通過組合使用Vue組件、Vuex狀態(tài)管理、Axios網(wǎng)絡(luò)請(qǐng)求等技術(shù)來實(shí)現(xiàn)一個(gè)完整的登錄功能。
本文將基于一個(gè)實(shí)際的Vue.js項(xiàng)目代碼,詳細(xì)解析登錄功能的實(shí)現(xiàn)過程。我們將從表單的實(shí)現(xiàn)開始,逐步深入到表單驗(yàn)證、接口調(diào)用、狀態(tài)管理以及登錄成功與失敗的處理。
2. 項(xiàng)目結(jié)構(gòu)概述
在開始之前,我們先簡(jiǎn)單了解一下項(xiàng)目的結(jié)構(gòu)。項(xiàng)目的登錄功能主要由以下幾個(gè)部分組成:
- 登錄組件:負(fù)責(zé)渲染登錄表單,并處理用戶的輸入。
- Vuex Store:負(fù)責(zé)管理用戶登錄狀態(tài),包括登錄請(qǐng)求的發(fā)起和響應(yīng)處理。
- API模塊:負(fù)責(zé)與后端接口進(jìn)行通信,發(fā)送登錄請(qǐng)求并接收響應(yīng)。
3. 登錄表單的實(shí)現(xiàn)
登錄表單是用戶與系統(tǒng)交互的入口。在我們的項(xiàng)目中,登錄表單使用了Ant Design Vue組件庫(kù)來實(shí)現(xiàn)。以下是登錄表單的核心代碼:
<template>
<a-col class="main line_input">
<a-form
id="formLogin"
class="user-layout-login"
ref="formLogin"
:form="form"
hideRequiredMark
@submit="handleSubmit"
>
<div class="title"><span>1nmob</span></div>
<a-alert v-if="isLoginError" type="error" showIcon style="margin-bottom: 24px;" message="賬戶或密碼錯(cuò)誤" />
<!-- 登錄方式選擇 -->
<a-radio-group v-model="loginType" style="margin-bottom: 24px;">
<a-radio-button value="account">賬號(hào)密碼登錄</a-radio-button>
<a-radio-button value="phone">手機(jī)號(hào)登錄</a-radio-button>
</a-radio-group>
<!-- 賬號(hào)密碼登錄 -->
<div v-if="loginType === 'account'">
<a-row type="flex" class="padding_bottom">
<a-col flex="58px">
<span class="labels">賬號(hào):</span>
</a-col>
<a-col flex="310px">
<a-form-item>
<a-input
size="small"
type="text"
placeholder=""
ref="userCodeDom"
v-decorator="[
'userCode',
{rules: [{ required: true, message: '請(qǐng)輸入帳戶名或郵箱地址' }, { validator: handleuserCodeOrEmail }], validateTrigger: 'change'}
]"
>
</a-input>
</a-form-item>
</a-col>
</a-row>
<a-row type="flex">
<a-col flex="58px">
<span class="labels">密碼:</span>
</a-col>
<a-col flex="310px">
<a-form-item>
<a-input-password
size="small"
class="my_password"
placeholder=""
ref="pwdDom"
v-decorator="[
'pwd',
{rules: [{ required: true, message: '請(qǐng)輸入密碼' }], validateTrigger: 'blur'}
]"
>
</a-input-password>
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 手機(jī)號(hào)登錄 -->
<div v-if="loginType === 'phone'">
<a-row type="flex" class="padding_bottom">
<a-col flex="58px">
<span class="labels">手機(jī)號(hào):</span>
</a-col>
<a-col flex="310px">
<a-form-item>
<a-input
size="small"
type="text"
placeholder=""
ref="phoneDom"
v-decorator="[
'phone',
{rules: [{ required: true, message: '請(qǐng)輸入手機(jī)號(hào)' }], validateTrigger: 'change'}
]"
>
</a-input>
</a-form-item>
</a-col>
</a-row>
<a-row type="flex">
<a-col flex="58px">
<span class="labels">驗(yàn)證碼:</span>
</a-col>
<a-col flex="200px">
<a-form-item>
<a-input
size="small"
type="text"
placeholder=""
ref="captchaDom"
v-decorator="[
'captcha',
{rules: [{ required: true, message: '請(qǐng)輸入驗(yàn)證碼' }], validateTrigger: 'blur'}
]"
>
</a-input>
</a-form-item>
</a-col>
<a-col flex="110px">
<a-button
size="small"
:disabled="state.smsSendBtn"
@click="getCaptcha"
>
{{ state.smsSendBtn ? `${state.time}秒后重新獲取` : '獲取驗(yàn)證碼' }}
</a-button>
</a-col>
</a-row>
</div>
<a-form-item>
<router-link
:to="{ name: 'recover', params: { user: 'aaa'} }"
class="forge-password"
style="float: right;"
>忘記密碼?</router-link>
</a-form-item>
<div style="textAlign:center">
<a-form-item style="margin-bottom:0px">
<a-button
size="large"
type="primary"
htmlType="submit"
class="login-button"
:loading="state.loginBtn"
:disabled="state.loginBtn"
>確定</a-button>
</a-form-item>
</div>
</a-form>
</a-col>
</template>
在這個(gè)表單中,我們使用了a-form組件來包裹整個(gè)表單,并通過v-decorator指令來實(shí)現(xiàn)表單驗(yàn)證。用戶可以選擇通過賬號(hào)密碼或手機(jī)號(hào)登錄,表單會(huì)根據(jù)用戶的選擇動(dòng)態(tài)渲染不同的輸入項(xiàng)。
4. 表單驗(yàn)證
表單驗(yàn)證是確保用戶輸入數(shù)據(jù)合法性的重要步驟。在我們的項(xiàng)目中,表單驗(yàn)證通過Ant Design Vue的v-decorator指令來實(shí)現(xiàn)。以下是表單驗(yàn)證的核心代碼:
methods: {
handleuserCodeOrEmail (rule, value, callback) {
const { state } = this
const regex = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/
if (regex.test(value)) {
state.loginType = 0
} else {
state.loginType = 1
}
callback()
},
handleSubmit (e) {
e.preventDefault()
const {
form: { validateFields },
state,
loginType,
Login
} = this
state.loginBtn = true
const validateFieldsKey = loginType === 'account' ? ['userCode', 'pwd'] : ['phone', 'captcha']
validateFields(validateFieldsKey, { force: true }, (err, values) => {
if (!err) {
const loginParams = { ...values }
if (loginType === 'account') {
delete loginParams.userCode
loginParams[!state.loginType ? 'email' : 'userCode'] = values.userCode
loginParams.pwd = md5(values.pwd)
} else {
loginParams.phone = values.phone
loginParams.captcha = values.captcha
}
Login(loginParams)
.then((res) => {
if (res.code === this.CONSTVAL.SUCCESSCODE) {
this.loginSuccess(res)
} else {
this.requestFailed(res)
}
})
.catch(err => this.requestFailed(err))
.finally(() => {
state.loginBtn = false
})
} else {
setTimeout(() => {
state.loginBtn = false
}, 600)
}
})
}
}
在handleSubmit方法中,我們首先調(diào)用validateFields方法對(duì)表單進(jìn)行驗(yàn)證。如果驗(yàn)證通過,則構(gòu)造登錄參數(shù)并調(diào)用Login方法進(jìn)行登錄。
5. 登錄接口的調(diào)用
登錄接口的調(diào)用是通過Vuex的action來實(shí)現(xiàn)的。以下是登錄接口調(diào)用的核心代碼:
methods: {
...mapActions(['Login', 'Logout']),
handleSubmit (e) {
e.preventDefault()
const {
form: { validateFields },
state,
loginType,
Login
} = this
state.loginBtn = true
const validateFieldsKey = loginType === 'account' ? ['userCode', 'pwd'] : ['phone', 'captcha']
validateFields(validateFieldsKey, { force: true }, (err, values) => {
if (!err) {
const loginParams = { ...values }
if (loginType === 'account') {
delete loginParams.userCode
loginParams[!state.loginType ? 'email' : 'userCode'] = values.userCode
loginParams.pwd = md5(values.pwd)
} else {
loginParams.phone = values.phone
loginParams.captcha = values.captcha
}
Login(loginParams)
.then((res) => {
if (res.code === this.CONSTVAL.SUCCESSCODE) {
this.loginSuccess(res)
} else {
this.requestFailed(res)
}
})
.catch(err => this.requestFailed(err))
.finally(() => {
state.loginBtn = false
})
} else {
setTimeout(() => {
state.loginBtn = false
}, 600)
}
})
}
}
在handleSubmit方法中,我們通過Login action來調(diào)用登錄接口。Login action會(huì)在Vuex store中定義,通常使用Axios來發(fā)送HTTP請(qǐng)求。
6. Vuex狀態(tài)管理
Vuex是Vue.js的官方狀態(tài)管理庫(kù),用于管理應(yīng)用中的共享狀態(tài)。在我們的項(xiàng)目中,Vuex負(fù)責(zé)管理用戶登錄狀態(tài)。以下是Vuex store的核心代碼:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
user: null,
token: null
},
mutations: {
setUser (state, user) {
state.user = user
},
setToken (state, token) {
state.token = token
}
},
actions: {
Login ({ commit }, loginParams) {
return axios.post('/api/login', loginParams)
.then(response => {
commit('setUser', response.data.user)
commit('setToken', response.data.token)
return response
})
},
Logout ({ commit }) {
commit('setUser', null)
commit('setToken', null)
}
}
})
在Vuex store中,我們定義了Login和Logout兩個(gè)action,分別用于處理登錄和注銷操作。登錄成功后,我們會(huì)將用戶信息和token存儲(chǔ)到state中。
7. 登錄成功與失敗的處理
登錄成功或失敗后,我們需要根據(jù)接口返回的結(jié)果進(jìn)行相應(yīng)的處理。以下是登錄成功與失敗處理的代碼:
methods: {
loginSuccess (res) {
this.setUserCode(res.data.userCode)
this.setAccessWay(res.data.accessWay)
this.setUserPic(res.data.userPic)
this.setCompanyId(res.data.companyId)
this.setAccountType(res.data.accessWay)
this.setTokenTime(res.data.tokenTime)
this.$router.push({ path: '/' })
setTimeout(() => {
this.$notification.success({
message: '歡迎',
description: `${timeFix()},歡迎回來`
})
}, 1000)
this.isLoginError = false
},
requestFailed (err) {
this.isLoginError = true
this.$notification['error']({
message: '錯(cuò)誤',
description: ((err.response || {}).data || {}).message || '請(qǐng)求出現(xiàn)錯(cuò)誤,請(qǐng)稍后再試',
duration: 4
})
}
}
在loginSuccess方法中,我們將用戶信息存儲(chǔ)到Vuex state中,并跳轉(zhuǎn)到首頁(yè)。在requestFailed方法中,我們顯示錯(cuò)誤信息,提示用戶登錄失敗。
8. 總結(jié)
通過本文的詳細(xì)解析,我們了解了如何在Vue.js項(xiàng)目中實(shí)現(xiàn)一個(gè)完整的登錄功能。我們從表單的實(shí)現(xiàn)開始,逐步深入到表單驗(yàn)證、接口調(diào)用、狀態(tài)管理以及登錄成功與失敗的處理。希望本文能幫助開發(fā)者更好地理解和實(shí)現(xiàn)類似功能。
在實(shí)際開發(fā)中,登錄功能可能會(huì)更加復(fù)雜,涉及到更多的安全性和用戶體驗(yàn)優(yōu)化。但無論如何,掌握這些基礎(chǔ)知識(shí)是構(gòu)建一個(gè)健壯的登錄功能的前提。
以上就是基于Vue.js實(shí)現(xiàn)一個(gè)完整的登錄功能的詳細(xì)內(nèi)容,更多關(guān)于Vue.js登錄功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue Render函數(shù)原理及代碼實(shí)例解析
這篇文章主要介紹了Vue Render函數(shù)原理及代碼實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
vue3?setup中父組件通過Ref調(diào)用子組件的方法(實(shí)例代碼)
這篇文章主要介紹了vue3?setup中父組件通過Ref調(diào)用子組件的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08

