用户登录功能是Web应用中最常见的功能之一。它通常包括表单输入、数据验证、接口调用、状态管理等多个步骤。在Vue.js中,我们可以通过组合使用Vue组件、Vuex状态管理、Axios网络请求等技术来实现一个完整的登录功能。
本文将基于一个实际的Vue.js项目代码,详细解析登录功能的实现过程。我们将从表单的实现开始,逐步深入到表单验证、接口调用、状态管理以及登录成功与失败的处理。
在开始之前,我们先简单了解一下项目的结构。项目的登录功能主要由以下几个部分组成:
登录表单是用户与系统交互的入口。在我们的项目中,登录表单使用了Ant Design Vue组件库来实现。以下是登录表单的核心代码:
<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="账户或密码错误" />
<!-- 登录方式选择 -->
<a-radio-group v-model="loginType" style="margin-bottom: 24px;">
<a-radio-button value="account">账号密码登录</a-radio-button>
<a-radio-button value="phone">手机号登录</a-radio-button>
</a-radio-group>
<!-- 账号密码登录 -->
<div v-if="loginType === 'account'">
<a-row type="flex" class="padding_bottom">
<a-col flex="58px">
<span class="labels">账号:</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: '请输入帐户名或邮箱地址' }, { 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: '请输入密码' }], validateTrigger: 'blur'}
]"
>
</a-input-password>
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 手机号登录 -->
<div v-if="loginType === 'phone'">
<a-row type="flex" class="padding_bottom">
<a-col flex="58px">
<span class="labels">手机号:</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: '请输入手机号' }], 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="200px">
<a-form-item>
<a-input
size="small"
type="text"
placeholder=""
ref="captchaDom"
v-decorator="[
'captcha',
{rules: [{ required: true, message: '请输入验证码' }], 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}秒后重新获取` : '获取验证码' }}
</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>在这个表单中,我们使用了a-form组件来包裹整个表单,并通过v-decorator指令来实现表单验证。用户可以选择通过账号密码或手机号登录,表单会根据用户的选择动态渲染不同的输入项。
表单验证是确保用户输入数据合法性的重要步骤。在我们的项目中,表单验证通过Ant Design Vue的v-decorator指令来实现。以下是表单验证的核心代码:
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方法中,我们首先调用validateFields方法对表单进行验证。如果验证通过,则构造登录参数并调用Login方法进行登录。
登录接口的调用是通过Vuex的action来实现的。以下是登录接口调用的核心代码:
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来调用登录接口。Login action会在Vuex store中定义,通常使用Axios来发送HTTP请求。
Vuex是Vue.js的官方状态管理库,用于管理应用中的共享状态。在我们的项目中,Vuex负责管理用户登录状态。以下是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两个action,分别用于处理登录和注销操作。登录成功后,我们会将用户信息和token存储到state中。
登录成功或失败后,我们需要根据接口返回的结果进行相应的处理。以下是登录成功与失败处理的代码:
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: '错误',
description: ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试',
duration: 4
})
}
}在loginSuccess方法中,我们将用户信息存储到Vuex state中,并跳转到首页。在requestFailed方法中,我们显示错误信息,提示用户登录失败。
通过本文的详细解析,我们了解了如何在Vue.js项目中实现一个完整的登录功能。我们从表单的实现开始,逐步深入到表单验证、接口调用、状态管理以及登录成功与失败的处理。希望本文能帮助开发者更好地理解和实现类似功能。
在实际开发中,登录功能可能会更加复杂,涉及到更多的安全性和用户体验优化。但无论如何,掌握这些基础知识是构建一个健壮的登录功能的前提。