Vue登录组件和注册组件的封装
用到了Element-UI,Vuex,Axios等相关知识
登录组件
<template>
<div class="Login">
<div class="login-box">
<el-form :model="loginForm" :rules="loginRule" ref="loginRef" label-width="100px" class="demo-ruleForm loginForm">
<el-form-item label="账号" prop="userName" label-width="60px">
<el-input v-model="loginForm.userName" clearable></el-input>
</el-form-item>
<el-form-item label="密码" prop="password" label-width="60px">
<el-input v-model="loginForm.password" type="password" show-password @keyup.enter.native="keyDown"></el-input>
</el-form-item>
<el-form-item class="btns">
<el-button type="primary" round @click="login">登录</el-button>
<el-button type="primary" round @click="register">注册</el-button>
</el-form-item>
</el-form>
</div>
<img src="../assets/img/background.jpg" width="100%">
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
name: "Login",
data(){
// 用户名的校验方法
let validateName = (rule, value, callback) => {
if (!value) {
return callback(new Error("请输入用户名"));
}
// 用户名以字母开头,长度在5-16之间,允许字母数字下划线
const userNameRule = /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/;
if (userNameRule.test(value)) {
this.$refs.loginRef.validateField("checkPass");
return callback();
} else {
return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
}
};
// 密码的校验方法
let validatePass = (rule, value, callback) => {
if (value === "") {
return callback(new Error("请输入密码"));
}
// 密码以字母开头,长度在6-18之间,允许字母数字和下划线
const passwordRule = /^[a-zA-Z]\w{5,17}$/;
if (passwordRule.test(value)) {
this.$refs.loginRef.validateField("checkPass");
return callback();
} else {
return callback(
new Error("字母开头,长度6-18之间,允许字母数字和下划线")
);
}
};
return{
loginForm:{
userName:'',
password:''
},
loginRule:{
userName:[{ validator: validateName, trigger: "blur" }],
password: [{ validator: validatePass, trigger: "blur" }]
}
}
},
methods:{
...mapActions(['setUser']),
login(){
// 对整个表单进行校验的方法,参数为一个回调函数。该回调函数会在校验结束后被调用,
// 并传入两个参数:是否校验成功和未通过校验的字段。若不传入回调函数,则会返回一个 promise
this.$refs.loginRef.validate(async valid=> {
// valid回调函数里面的Boolean值,实验的结果
if (!valid)// valid为false不发起请求,valid为true时才能发出请求
return;
// 发起网络请求,提交数据
const res = await this.$http.post('/api//users/login',this.loginForm)
// console.log(res)
if(res.status !== 200){
return this.$message.error(res.data.msg)
}
this.$message.success(res.data.msg)
// 1.将登录成功之后token,保存到客户端的sessionStorage中
// 1.1 项目中除了登录页面之外的其他API接口,必须在登录之后才能访问
// 1.2 token只应在当前网站打开期间生效,所以将token 保存在sessionStorage 中
// window.sessionStorage.setItem("token",res.data.token);
// 登录信息存到本地
let user = JSON.stringify(res.data.user);
localStorage.setItem("user", user);
//提交到Vuex中的setUser方法中保存用户状态
this.setUser(res.data.user)
await this.$router.push({path:'/homeMain',query:{userName:this.loginForm.userName}})
// this.login(); // 定义的登录方法
})
},
register(){
this.$router.push('/register')
},
// 点击回车键登录
keyDown() {
// 回车则执行登录方法 enter键的ASCII是13
// if (e.keyCode === 13) {
this.login(); // 定义的登录方法
// }
},
},
}
</script>
<style>
.Login .login-box{
/*background-color:#2B2B2B;*/
background:rgba(0,0,0,0.3);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 50px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.loginForm{
width: 400px;
padding: 20px;
}
.el-textarea__inner,.el-input__inner{
background: transparent !important;
color: white;
}
</style>
-
效果图
-
import { mapActions } from “vuex”;
这里用到了vueX来保存登录的状态 -
@keyup.enter.native=“keyDown” 输入框回车事件,即敲回车键就会触发登录按钮事件
// 点击回车键登录
keyDown() {
// 回车则执行登录方法 enter键的ASCII是13
// if (e.keyCode === 13) {
this.login(); // 定义的登录方法
// }
},
- 特别注意:提交表单的之前需要对表单进行验证
this.$refs.loginRef.validate(async valid=> {
// valid回调函数里面的Boolean值,实验的结果
if (!valid)// valid为false不发起请求,valid为true时才能发出请求
return;
//接下来就是网络请求了。
- 网络请求发送完毕后,就需要保存用户登录状态,保存登录状态可以用本地缓存,也可以用vuex,我这里用的用vuex来保存
- 后端API接口提供token的话就需用到这个方法:
- // 1.2 token只应在当前网站打开期间生效,所以将token 保存在sessionStorage 中
// window.sessionStorage.setItem(“token”,res.data.token);
vueX中定义user模板来保存登录状态
export default {
state:{
user:'',// 登录的用户
showLogin:false // 用于控制是否显示登录组件
},
getters:{
// 获取用户的状态
getUser(state){
return state.user
},
//是否跳转到登录页面
getShowLogin(state){
return state.showLogin
}
},
mutations:{
//用户登录状态存放区
setUser(state,payload){
state.user = payload
},
setShowLogin(state,payload){
state.showLogin = payload
}
},
actions:{
setUser({commit}, payload) {
commit('setUser',payload)
},
setShowLogin({commit}, payload) {
commit('setShowLogin',payload)
}
}
}
注册组件
注册组件与登录组件极为相识,就多添加了再次验证密码这个功能,
<template>
<div class="Register-box">
<div class="Register">
<el-form :model="registerForm" :rules="registerRule" ref="registerRef" label-width="100px" class="demo-ruleForm registerForm">
<el-form-item label="账号" prop="userName" label-width="70px">
<el-input v-model="registerForm.userName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password" label-width="70px">
<el-input v-model="registerForm.password" type="password" show-password></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="confirmPassword" label-width="70px">
<el-input v-model="registerForm.confirmPassword" type="password" show-password @keyup.enter.native="keyDown"></el-input>
</el-form-item>
<el-form-item class="btns">
<el-button type="primary" round @click="register">完成</el-button>
</el-form-item>
</el-form>
</div>
<img src="../assets/img/background.jpg" width="100%">
</div>
</template>
<script>
export default {
name: "Register",
data() {
// 用户名的校验方法
let validateName = (rule, value, callback) => {
if (!value) {
return callback(new Error("请输入用户名"));
}
// 用户名以字母开头,长度在5-16之间,允许字母数字下划线
const userNameRule = /^[a-zA-Z][a-zA-Z0-9_]{4,15}$/;
if (userNameRule.test(value)) {
this.$refs.registerRef.validateField("checkPass");
return callback();
} else {
return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
}
};
// 密码的校验方法
let validatePass = (rule, value, callback) => {
if (value === "") {
return callback(new Error("请输入密码"));
}
// 密码以字母开头,长度在6-18之间,允许字母数字和下划线
const passwordRule = /^[a-zA-Z]\w{5,17}$/;
if (passwordRule.test(value)) {
this.$refs.registerRef.validateField("checkPass");
return callback();
} else {
return callback(
new Error("字母开头,长度6-18之间,允许字母数字和下划线")
);
}
};
// 确认密码的校验方法
let validateConfirmPass = (rule, value, callback) => {
if (value === "") {
return callback(new Error("请输入确认密码"));
}
// 校验是否以密码一致
if (this.registerForm.password !== "" && value === this.registerForm.password) {
this.$refs.registerRef.validateField("checkPass");
return callback();
} else {
return callback(new Error("两次输入的密码不一致"));
}
};
return {
registerForm: {
userName: '',
password: '',
confirmPassword:''
},
registerRule: {
userName: [{validator: validateName, trigger: "blur"}],
password: [{validator: validatePass, trigger: "blur"}],
confirmPassword: [{ validator: validateConfirmPass, trigger: "blur" }]
}
}
},
methods:{
register(){
this.$refs.registerRef.validate(async valid=> {
// valid回调函数里面的Boolean值,实验的结果
if (!valid)// valid为false不发起请求,valid为true时才能发出请求
return;
// 发起网络请求,提交数据
const res = await this.$http.post('/api/users/register',{
userName:this.registerForm.userName,
password:this.registerForm.password
})
console.log(res)
if (res.status !== 200){
return this.$message.error(res.data.msg)
}
this.$message.success(res.data.msg)
await this.$router.push('/login')
})
},
// 点击回车键登录
keyDown() {
this.register(); //
},
},
}
</script>
<style>
.Register{
background:rgba(0,0,0,0.3);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 50px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.registerForm{
width: 400px;
padding: 20px;
}
.el-textarea__inner,.el-input__inner{
background: transparent !important;
color: white;
}
</style>