一. 登录注册页面 [element-plus 表单 & 表单校验]
功能需求说明:
(1). 注册登录静态结构 &基本切换
(2). 注册功能(校验+注册)
(3). 登录功能(校验 +登录+存token)
1. App.vue预留路由出口
App.vue
<script setup></script>
<template>
<div>
<!-- App.vue 只需要留一个路由出口 router-view即可 -->
<router-view></router-view>
</div>
</template>
<style scoped></style>
2. 安装 element-plus 图标库
pnpm i @element-plus/icons-vue
3. 登录页静态结构
src\views\login\LoginPage.vue
<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref } from 'vue'
const isRegister = ref(true)
</script>
<template>
<!--
el-row表示一行,一行分成24份
el-col表示列
(1):span='12' 表示在一行中,占12份(50%)
(2):pan='6' 表示在一行中,占6份(25%)
(3):offset="3" 代表在一行中,左侧margin份数
el-form 整个表单组件
el-form-item 表单的一行(一个表单域)
el-input 表单元素(输入框)
-->
<el-row class="login-page">
<el-col :span="12" class="bg"></el-col>
<el-col :span="6" :offset="3" class="form">
<!-- 注册相关表单 -->
<el-form ref="form" size="large" autocomplete="off" v-if="isRegister">
<el-form-item>
<h1>注册</h1>
</el-form-item>
<el-form-item>
<el-input :prefix-icon="User" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item>
<el-input
:prefix-icon="Lock"
type="password"
placeholder="请输入密码"
></el-input>
</el-form-item>
<el-form-item>
<el-input
:prefix-icon="Lock"
type="password"
placeholder="请输入再次密码"
></el-input>
</el-form-item>
<el-form-item>
<el-button class="button" type="primary" auto-insert-space>
注册
</el-button>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="isRegister = false">
← 返回
</el-link>
</el-form-item>
</el-form>
<!-- 登陆相关表单 -->
<el-form ref="form" size="large" autocomplete="off" v-else>
<el-form-item>
<h1>登录</h1>
</el-form-item>
<el-form-item>
<el-input :prefix-icon="User" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item>
<el-input
name="password"
:prefix-icon="Lock"
type="password"
placeholder="请输入密码"
></el-input>
</el-form-item>
<el-form-item class="flex">
<div class="flex">
<el-checkbox>记住我</el-checkbox>
<el-link type="primary" :underline="false">忘记密码?</el-link>
</div>
</el-form-item>
<el-form-item>
<el-button class="button" type="primary" auto-insert-space
>登录</el-button
>
</el-form-item>
<el-form-item class="flex">
<el-link type="info" :underline="false" @click="isRegister = true">
注册 →
</el-link>
</el-form-item>
</el-form>
</el-col>
</el-row>
</template>
<style lang="scss" scoped>
.login-page {
height: 100vh;
background-color: #fff;
.bg {
background:
url('@/assets/logo2.png') no-repeat 60% center / 240px auto,
url('@/assets/login_bg.jpg') no-repeat center / cover;
border-radius: 0 20px 20px 0;
}
.form {
display: flex;
flex-direction: column;
justify-content: center;
user-select: none;
.title {
margin: 0 auto;
}
.button {
width: 100%;
}
.flex {
width: 100%;
display: flex;
justify-content: space-between;
}
}
}
</style>
二. 注册校验
src\ views\ login\ LoginPage.vue
需要四步:
(1) el-form => :model="ruleForm" 绑定的整个form的数据对象{xxx,xxx,xxx}
(2) el-form => :rules="rules" 绑定的整个rules规则对象 {xxx,xxx,xxx}
(3) 表单元素 => v-model="ruleForm.xxx" 给表单元素,绑定form的子属性
(4) el-form-item => prop配置生效的是那个校验规则(和 rules中的字段要对应)
1. 定义表单对象
<script setup>
import { User, Lock } from '@element-plus/icons-vue'
import { ref } from 'vue'
const isRegister = ref(true)
// 注册,整个用于提交的form对象
const formModel = ref({
username: '',
password: '',
repassword: ''
})
</script>
2. 定义校验规则
<script setup>
...
// 注册,整个用于提交的form对象
...
// 整个表单的校验规则
// 1. 非空校验 required: true ,message消息提示, trigger触发校验的实际 blur(失焦)change(实时)
// 2. 长度校验 mix:xxx, max:xxx
// 3. 正则校验 pattern: 正则规则 \S:非空字符
// 4. 自定义校验 => 自己写逻辑校验(校验函数)
// validator: (rule, value, callback)
// (1) rule 当前校验规则相关的信息
// (2) value 所校验的表单元素目前的表单值
// (3) callback 无论成功还是失败,都需要 callback 回调
// -callback() 校验成功
// -callback(new Error(错误信息)) 校验失败
const rules = {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 5, max: 10, message: '用户名必须是 5-10位 的字符', trigger: 'blur' }
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
pattern: /^\S{6,15}$/,
message: '密码必须 是6-15位 的非空字符',
trigger: 'blur'
}
],
repassword: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{
pattern: /^\S{6,15}$/,
message: '密码必须 是6-15位 的非空字符',
trigger: 'blur'
},
{
// 自定义校验
validator: (rule, value, callback) => {
// 判断 value 和 当前 form 中收集的 password 是否一致
if (value !== formModel.value.password) {
callback(new Error('两次输入的密码不一致'))
} else {
callback() // 就算校验成功,也需要callback
}
},
trigger: 'blur'
}
]
}
</script>
3. 用户名绑定校验
<!--1. el-form绑定整个form数据对象 和 整个rules规则对象-->
<el-form :model="formModel" :rules="rules" ...>
<!--2.el-form-item绑定对应的校验规则 -->
<el-form-item prop="username">
<!--3. el-input 绑定form的子属性-->
<el-input v-model="formModel.username" ... placeholder="请输入用户名"></el-input>
</el-form-item>
...
</el-form>
4. 密码绑定校验
<!--1. el-form绑定整个form数据对象 和 整个rules规则对象-->
<el-form :model="formModel" :rules="rules" ...>
...
<!--2.el-form-item绑定对应的校验规则 -->
<el-form-item prop="password">
<!--3. el-input 绑定form的子属性-->
<el-input v-model="formModel.password" ... placeholder="请输入密码"></el-input>
</el-form-item>
...
</el-form>
5. 确认密码绑定校验
<!--1. el-form绑定整个form数据对象 和 整个rules规则对象-->
<el-form :model="formModel" :rules="rules" ...>
...
<!--2.el-form-item绑定对应的校验规则 -->
<el-form-item prop="repassword">
<!--3. el-input 绑定form的子属性-->
<el-input v-model="formModel.repassword" ... placeholder="请输入再次密码"></el-input>
</el-form-item>
...
</el-form>
三. 注册预校验
1. 通过 ref 获取到 表单组件
src\views\login\LoginPage.vue
<script>
const form = ref()
</ script>
<template>
<el-form ref="form" ...>注册 ...</el-form>
</template>
2. 定义点击事件进行预校验
src\views\login\LoginPage.vue
<script>
const register = async () => {
//注册成功之前,先进行校验,校验成功 ->请求, 校验失败 ->自动提示
await form.value.validate() // validate:校验
console.log('开始注册请求')
}
</script>
<template>
<el-button @click="register" ...>注册</el-button>
</template>
3. 封装注册接口
src\api\user.js
import request from '@/utils/request'
// 注册接口
export const userRegisterService = ({ username, password, repassword }) =>
request.post('/api/reg', { username, password, repassword })
4. 页面中调用
src\views\login\LoginPage.vue
<script>
import { userRegisterService } from '@/api/user.js' // 导入注册接口
...
const register = async () => {
//注册成功之前,先进行校验,校验成功 ->请求, 校验失败 ->自动提示
await form.value.validate() // validate:校验
await userRegisterService(formModel.value) // 调用注册接口
ElMessage.success('注册成功')
isRegister.value = false // 切换到登录
}
</script>
5. eslintrc中声明全局变量名
解决ElMessage报错问题, .eslintrc.cjs
module.exports = {
...
rules: {
...
},
// 配置全局变量
globals: {
ElMessage: 'readonly',
ElMessageBox: 'readonly',
ElLoading: 'readonly'
}
}
四. 登录校验
复用注册的校验规则 src\views\login\LoginPage.vue
1. 用户名校验
<template>
<!-- 1. 共用注册定义的对象 和 校验规则 -->
<el-form :model="formModel" :rules="rules" ... >
<!-- 2. 绑定对应的校验规则 -->
<el-form-item prop="username">
<!--3. 输入框双向绑定form对象属性 -->
<el-input v-model="formModel.username" ... placeholder="请输入用户名"></el-input>
</el-form-item>
</el-form>
</template>
2. 密码校验
<template>
<!-- 1. 共用注册定义的对象 和 校验规则 -->
<el-form :model="formModel" :rules="rules" ... >
<!-- 2. 绑定对应的校验规则 -->
<el-form-item prop="password">
<!--3. 输入框双向绑定form对象属性 -->
<el-input v-model="formModel.password" ... placeholder="请输入密码"></el-input>
</el-form-item>
</el-form>
</template>
3. 登录注册切换重置输入框
<script>
import { ref, watch } from 'vue'
...
// 切换的时候,重置表单内容
watch(isRegister, () => {
formModel.value = {
username: '',
password: '',
repassword: ''
}
})
</script>
五. 登录预校验
1. 通过 ref 获取到 表单组件
src\views\login\LoginPage.vue
<script>
const form = ref()
</ script>
<template>
<el-form ref="form" ...>登录 ...</el-form>
</template>
2. 定义点击事件进行预校验
src\views\login\LoginPage.vue
<script>
const login = async () => {
await form.value.validate()
console.log('开始登录')
}
</script>
<template>
<el-button @click="login" ...>登录</el-button>
</template>
3. 封装登录api
src\api\user.js
import request from '@/utils/request'
...
// 登录接口
export const userLoginService = ({ username, password }) =>
request.post('/api/login', {
username,
password
})
4. 页面中调用 & 持久化token
<script>
import { userRegisterService, userLoginService } from '@/api/user.js' // 导入user接口
import { useUserStore } from '@/stores' // 导入user仓库
import { useRouter } from 'vue-router' // 导入路由对象
...
const userStore = useUserStore()
const router = useRouter()
const login = async () => {
await form.value.validate() // 预校验
const res = await userLoginService(formModel.value) // 调用登录接口
userStore.setToken(res.data.token) // 将token保存在pinia仓库
console.log(userStore.token)
ElMessage.success('登录成功')
router.push('/') // 跳转到首页
}
</script>