前言
项目地址
本项目是为开发一套容器化的开发、运行、测试环境,用以支持Web开发、程序设计等课程的实验教学。
任务
实现路由限制以及注册时的表单验证
路由限制
给需要登陆状态才能进入的页面添加meta属性
import { createRouter, createWebHistory } from 'vue-router';
import codingViewVue from '../views/coding-view.vue';
import registerViewVue from '../views/register-view.vue';
import loginhomeVue from '../views/loginhome.vue';
import loginViewVue from '../views/login-view.vue';
import forgetpasswViewVue from '../views/forgetpassw-view.vue';
import updatepasswViewVue from '../views/updatepassw-view.vue';
import resetpasswViewVue from '../views/resetpassw-view.vue';
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
name: "home",
component: codingViewVue,
meta:{
isLogin:false,
}
},
{
path: "/register",
name: "register-view",
component: registerViewVue,
meta:{
isLogin:false,
}
},
{
path: "/login",
name: "login-view",
component: loginViewVue,
meta:{
isLogin:false,
}
},
{
path: "/logout",
name: "coding-view",
component: codingViewVue,
meta:{
isLogin:false,
}
},
{
path: "/forget_password",
name: "forgetpassw-view",
component: forgetpasswViewVue,
meta:{
isLogin:false,
}
},
{
path: "/update_password",
name: "update_password",
component: updatepasswViewVue,
meta:{
isLogin:true,
}
},
{
path: "/reset_password",
name: "reset_password",
component: resetpasswViewVue,
meta:{
isLogin:false,
}
},
{
path: "/login_home",
name: "login_home",
component: loginhomeVue,
meta:{
isLogin:true,
}
},
],
});
export default router;
利用pinia实现全局状态管理
import { defineStore } from "pinia";
export const useLoginStore = defineStore({
id: "login",
state: () => ({
isLogin: Number(localStorage.getItem('isLogin') || '0'),
userId: localStorage.getItem('userId') || '',
userPassword: localStorage.getItem('userPassword') || '',
}),
getters: {
getIsLogin(state) {
return (state.isLogin == 1) ? true : false;
},
getUserId(state) {
return state.userId;
},
getUserPassword(state) {
return state.userPassword
}
},
actions: {
userLogin(id: string, pwd: string) {
this.isLogin = 1;
this.userId = id;
this.userPassword = pwd;
localStorage.setItem('isLogin', '1');
localStorage.setItem('userId', id);
localStorage.setItem('userPassword', pwd);
},
userLogout() {
this.isLogin = 0;
this.userId = '';
this.userPassword = '';
localStorage.setItem('isLogin', '0');
localStorage.setItem('userId', '');
localStorage.setItem('userPassword', '');
}
},
});
main.ts中实现路由限制
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import router from "./router";
import ElementPlus from "element-plus";
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/display.css'
import { GlobalCmComponent } from "codemirror-editor-vue3";
import { useLoginStore } from "./stores/store";
const app = createApp(App);
app.use(createPinia());
app.use(GlobalCmComponent);
app.use(ElementPlus);
app.use(router);
const store = useLoginStore();
router.beforeEach((to, from, next) => {
//获取登录信息
let isLogin = store.getIsLogin;
if (isLogin) { //已登录
if (!to.meta.isLogin) {
next({
path: '/login_home'
})
}else{
next();
}
} else { //未登录
if (to.meta.isLogin) {
next({
path: '/login',
})
} else {
next()
}
}
});
app.mount('#app')
表单验证
<!--注册界面-->
<template>
<div class="login-wrap">
<el-form
class="login-container"
:model="registerForm"
:rules="registerRules"
label-position="right"
label-width="80px"
>
<h1 class="title">注册</h1>
<el-form-item label="用户名称" prop="username">
<el-input type="text" placeholder="请输入名称" v-model="registerForm.username"></el-input>
</el-form-item>
<el-form-item label="用户邮箱" prop="useremail">
<el-input type="email" placeholder="请输入邮箱" v-model="registerForm.useremail" size="default"></el-input>
</el-form-item>
<el-form-item label="用户密码" prop="pass">
<el-tooltip content="<span>长度为8~15位,必须同时包含大小写字母及数字</span>" raw-content>
<el-input v-model="registerForm.pass" type="password" placeholder="请输入密码" show-password />
</el-tooltip>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input
v-model="registerForm.checkPass"
type="password"
placeholder="请再次输入密码"
show-password
/>
</el-form-item>
<el-form-item label="验证码" prop="checkCode">
<el-input v-model="registerForm.checkCode" placeholder="请输入验证码" />
</el-form-item>
<el-form-item label-width="100px">
<CharacterVerification ref="ver"></CharacterVerification>
</el-form-item>
<el-form-item label-width="0px">
<el-button type="primary" @click="registerUser()" style="width: 48%;">用户注册</el-button>
<el-button style="width: 48%;" @click="gotoLogin()">返回登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script lang="ts">
import { useRouter } from "vue-router";
import { ref, defineComponent, reactive } from 'vue';
import CharacterVerification from '../components/CharacterVerification.vue';
export default defineComponent({
components: { CharacterVerification },
setup() {
const router = useRouter();
//表单内容
const registerForm = reactive({
username: '',
useremail: '',
pass: '',
checkPass: '',
checkCode: ''
})
const ver = ref();
// 自定义验证规则
const validatePass = (rule: any, value: any, callback: any) => {
const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
if (registerForm.checkPass != null && registerForm.checkPass !== '') {
if (value != registerForm.checkPass) {
callback(new Error('输入密码不一致'));
}
}
if (!reg.test(value)) {
callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
}
callback();
}
const validateCheckPass = (rule: any, value: any, callback: any) => {
const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
if (value !== registerForm.pass) {
callback(new Error('两次密码输入不一致'));
}
if (!reg.test(value)) {
callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
}
callback();
}
//检查验证码是否正确
const validateVerificationCode = (rule: any, value: any, callback: any) => {
if (!ver.value.validate(value)) {
callback(new Error('验证码错误'));
} else {
callback()
}
}
// 定义校验规则
const registerRules = reactive({
username: [
{ required: true, message: '用户名称不能为空', trigger: 'blur' },
{ min: 2, max: 32, message: '名称长度只能在2~32之间', trigger: 'blur' }
],
useremail: [
{ required: true, message: '邮箱不能为空', trigger: 'blur' },
{ type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
],
pass: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
{ min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
{ min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
{ validator: validateCheckPass, trigger: 'blur' }
],
checkCode: [
{ required: true, message: '验证码不能为空', trigger: 'blur' },
{ validator: validateVerificationCode, trigger: 'blur' }
]
})
function registerUser() {
router.push({ path: "/login" });
}
function gotoLogin() {
router.push({ path: "/login" });
}
return {
ver,
registerForm,
registerRules,
registerUser,
gotoLogin,
}
}
})
</script>
<style>
.login-wrap {
box-sizing: border-box;
width: 100%;
height: 100%;
padding-top: 10%;
}
.login-container {
border-radius: 10px;
margin: 0px auto;
width: 350px;
padding: 30px 35px 15px 35px;
background: #fff;
border: 1px solid #eaeaea;
text-align: left;
box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}
.title {
margin: 0px auto 40px auto;
text-align: center;
color: #505458;
}
</style>