以简单的登录功能为例子
1.在util中创建loginValidators.ts
import { ref, reactive } from 'vue'interface User{email: string;password: string;
}export const loginUser=reactive<User>({email: '',password: ''
})interface Rules{email: {required: boolean;message: string;trigger: string;}[];password: ({required: boolean;message: string;trigger: string;min?: undefined;max?: undefined;} | {min: number;max: number;message: string;trigger: string;required?: undefined;})[];
}
export const rules=reactive<Rules>({email: [{ required: true, message: '密码不得为空', trigger: 'blur' }// {// required: true,// type: 'email',// message: 'email格式错误',// trigger: 'blur'// }],password: [{ required: true, message: '密码不得为空', trigger: 'blur' },{ min: 6, max: 30, message: '密码长度必须在6到30之间', trigger: 'blur' }]
})
2.在登录页面中引用刚才创建的验证ts
3.创建登录组件
传入得参数(此步骤在登录界面引用登录组件后传入的参数:查看第4步骤)
就可以使用ts中创建的参数
登录组件代码(可看可不看)
<template><!-- 登录 --><el-form:model="loginUser":rules="rules"ref="loginForm"label-width="100px"class="login-form sign-in-form"><el-form-item label="邮箱" prop="email"><el-input v-model="loginUser.email" placeholder="Enter Email..." /></el-form-item><el-form-item label="密码" prop="password"><el-inputv-model="loginUser.password"type="password"placeholder="Enter Password..."/></el-form-item><el-form-item><el-button@click="handleLogin('loginForm')"type="primary"class="submit-btn">提交</el-button></el-form-item><!-- 找回密码 --><el-form-item><p class="tiparea">忘记密码<a>立即找回</a></p></el-form-item></el-form>
</template><script lang="ts">
import { getCurrentInstance } from 'vue'
import { useRouter } from 'vue-router'
import { login } from '@/api/login'
export default {name: 'LoginForm',props: {loginUser: {type: Object,required: true},rules: {type: Object,required: true}},setup(props: any) {const router = useRouter()// 通过解构getCurrentInstance,获取this,这里的this就是ctx// @ts-ignoreconst { ctx,proxy } = getCurrentInstance()// 触发登录方法const handleLogin = (formName: string) => {console.log(ctx)ctx.$refs[formName].validate(async (valid: boolean) => {if (valid) {//await是等待的意思const res = await login(props.loginUser)// if(res==false){// proxy.$message.warning("res是方法返回来的数据")// }else{// proxy.$message.success("123")// router.push('/home')// } proxy.$message.success("123")router.push('/home')} else {console.log('error submit!')return false}})}return { handleLogin }}
}
</script>
<style scoped>
/* register */
.login-form,
.register-form {background-color: #fff;padding: 50px 80px 20px 20px;border-radius: 5px;box-shadow: 0px 5px 10px #cccc;
}.submit-btn {width: 100%;
}
.tiparea {text-align: right;font-size: 12px;color: #333;width: 100%;
}
.tiparea a {color: #409eff;
}
</style>
4.在登录页面中引入登录组件
登录界面代码(可看可不看)
<template><div class="container" :class="{ 'sign-up-mode': signUpMode }"><!-- form表单容器 --><div class="form-container"><div class="signin-signup"><!-- 登录 --><LoginForm :loginUser="loginUser" :rules="rules"></LoginForm><!-- 注册 --><RegisterForm :registerUser="registerUser" :registerRules="registerRules"></RegisterForm></div></div><!-- 左右切换动画 --><div class="panels-container"><div class="panel left-panel"><div class="content"><h3>Row,row,row your boat</h3><p>Gentlely down the stream</p><button @click="signUpMode = !signUpMode" class="btn transparent">注册</button></div><!-- <img src="@/assets" alt=""> --></div><div class="panel right-panel"><div class="content"><h3>Merrily,merrily,merrily,merrily,</h3><p>Life is but a dream</p><button @click="signUpMode = !signUpMode" class="btn transparent">登录</button></div><!-- <img src="@/assets" alt=""> --></div></div><!-- <el-form:model="loginUser":rules="rules"ref="loginForm"label-width="100px"class="login-form sign-in-form"><el-form-item label="邮箱" prop="email"><el-input v-model="loginUser.email" placeholder="Enter Email..." /></el-form-item><el-form-item label="密码" prop="password"><el-inputv-model="loginUser.password"type="password"placeholder="Enter Password..."/></el-form-item><el-form-item><el-button type="primary" class="submit-btn" @click="handleLogin('loginForm')">提交</el-button></el-form-item><el-form-item><p class="tiparea">忘记密码<a>立即找回</a></p></el-form-item></el-form> --></div>
</template><script lang="ts">
import {ref,reactive,getCurrentInstance } from 'vue'
import {loginUser,rules} from '@/utils/loginValidators' //登录验证规则
import {registerUser ,registerRules } from '@/utils/registerValidator' //注册验证规则
import LoginForm from '@/components/LoginForm.vue' //登录组件
import RegisterForm from '@/components/RegisterForm.vue' //注册组件export default {name: 'LoginRegister',components:{LoginForm,RegisterForm},setup() {// 登录/注册模式const signUpMode = ref(false)// 通过解构getCurrentInstance,获取this,这里的this就是ctx// @ts-ignore// const { ctx } = getCurrentInstance()// const loginUser=reactive({// email:'',// password:''// })// //校验规则// const rules=reactive({// email:[// {// required: true,// type: 'email',// message: 'email格式错误',// trigger: 'blur'// }// ],// password:[// {required:true,message:'密码不能为空',trigger:'blur'},// { min: 6, max: 30, message: '密码长度必须在6到30之间', trigger: 'blur' }// ]// })//提交// const handleLogin=(formName:string)=>{// console.log( ctx.loginUser.password)// ctx.$refs[formName].validate((valid:boolean)=>{// if (valid) {// console.log("提交吧")// }else{// console.log("不提交了")// return false// }// })// }return {signUpMode,loginUser,rules,registerUser,registerRules}}
}
</script>
<style scoped>
.container {position: relative;width: 100%;min-height: 100vh;background-color: #fff;overflow: hidden;
}
.form-container {position: absolute;left: 0;top: 0;width: 100%;height: 100%;
}
.signin-signup {position: relative;top: 50%;left: 75%;transform: translate(-50%, -50%);width: 44%;transition: 1s 0.7s ease-in-out;display: grid;grid-template-columns: 1fr;z-index: 5;
}/* 左右切换动画 */
.social-text {padding: 0.7rem 0;font-size: 1rem;
}.social-media {display: flex;justify-content: center;
}.social-icon {height: 46px;width: 46px;display: flex;justify-content: center;align-items: center;margin: 0 0.45rem;color: #333;border-radius: 50%;border: 1px solid #333;text-decoration: none;font-size: 1.1rem;transition: 0.3s;
}.social-icon:hover {color: #4481eb;border-color: #4481eb;
}.btn {width: 150px;background-color: #5995fd;border: none;outline: none;height: 49px;border-radius: 49px;color: #fff;text-transform: uppercase;font-weight: 600;margin: 10px 0;cursor: pointer;transition: 0.5s;
}.btn:hover {background-color: #4d84e2;
}
.panels-container {position: absolute;height: 100%;width: 100%;top: 0;left: 0;display: grid;grid-template-columns: repeat(2, 1fr);
}.container:before {content: '';position: absolute;height: 2000px;width: 2000px;top: -10%;right: 48%;transform: translateY(-50%);background-image: linear-gradient(-45deg, #4481eb 0%, #04befe 100%);transition: 1.8s ease-in-out;border-radius: 50%;z-index: 6;
}.image {width: 100%;transition: transform 1.1s ease-in-out;transition-delay: 0.4s;
}.panel {display: flex;flex-direction: column;align-items: flex-end;justify-content: space-around;text-align: center;z-index: 6;
}.left-panel {pointer-events: all;padding: 3rem 17% 2rem 12%;
}.right-panel {pointer-events: none;padding: 3rem 12% 2rem 17%;
}.panel .content {color: #fff;transition: transform 0.9s ease-in-out;transition-delay: 0.6s;
}.panel h3 {font-weight: 600;line-height: 1;font-size: 1.5rem;
}.panel p {font-size: 0.95rem;padding: 0.7rem 0;
}.btn.transparent {margin: 0;background: none;border: 2px solid #fff;width: 130px;height: 41px;font-weight: 600;font-size: 0.8rem;
}.right-panel .image,
.right-panel .content {transform: translateX(800px);
}/* ANIMATION */.container.sign-up-mode:before {transform: translate(100%, -50%);right: 52%;
}.container.sign-up-mode .left-panel .image,
.container.sign-up-mode .left-panel .content {transform: translateX(-800px);
}.container.sign-up-mode .signin-signup {left: 25%;
}.container.sign-up-mode form.sign-up-form {opacity: 1;z-index: 2;
}.container.sign-up-mode form.sign-in-form {opacity: 0;z-index: 1;
}.container.sign-up-mode .right-panel .image,
.container.sign-up-mode .right-panel .content {transform: translateX(0%);
}.container.sign-up-mode .left-panel {pointer-events: none;
}.container.sign-up-mode .right-panel {pointer-events: all;
}@media (max-width: 870px) {.container {min-height: 800px;height: 100vh;}.signin-signup {width: 100%;top: 95%;transform: translate(-50%, -100%);transition: 1s 0.8s ease-in-out;}.signin-signup,.container.sign-up-mode .signin-signup {left: 50%;}.panels-container {grid-template-columns: 1fr;grid-template-rows: 1fr 2fr 1fr;}.panel {flex-direction: row;justify-content: space-around;align-items: center;padding: 2.5rem 8%;grid-column: 1 / 2;}.right-panel {grid-row: 3 / 4;}.left-panel {grid-row: 1 / 2;}.image {width: 200px;transition: transform 0.9s ease-in-out;transition-delay: 0.6s;}.panel .content {padding-right: 15%;transition: transform 0.9s ease-in-out;transition-delay: 0.8s;}.panel h3 {font-size: 1.2rem;}.panel p {font-size: 0.7rem;padding: 0.5rem 0;}.btn.transparent {width: 110px;height: 35px;font-size: 0.7rem;}.container:before {width: 1500px;height: 1500px;transform: translateX(-50%);left: 30%;bottom: 68%;right: initial;top: initial;transition: 2s ease-in-out;}.container.sign-up-mode:before {transform: translate(-50%, 100%);bottom: 32%;right: initial;}.container.sign-up-mode .left-panel .image,.container.sign-up-mode .left-panel .content {transform: translateY(-300px);}.container.sign-up-mode .right-panel .image,.container.sign-up-mode .right-panel .content {transform: translateY(0px);}.right-panel .image,.right-panel .content {transform: translateY(300px);}.container.sign-up-mode .signin-signup {top: 5%;transform: translate(-50%, 0);}
}@media (max-width: 570px) {form {padding: 0 1.5rem;}.image {display: none;}.panel .content {padding: 0.5rem 1rem;}.container {padding: 1.5rem;}.container:before {bottom: 72%;left: 50%;}.container.sign-up-mode:before {bottom: 28%;left: 50%;}
}/* 控制login & register显示 */
form {padding: 0rem 5rem;transition: all 0.2s 0.7s;overflow: hidden;
}form.sign-in-form {z-index: 2;
}form.sign-up-form {opacity: 0;z-index: 1;
}/* register */
.loginForm,
.registerForm {margin-top: 20px;background-color: #fff;padding: 20px 40px 20px 20px;border-radius: 5px;box-shadow: 0px 5px 10px #cccc;
}.submit-btn {width: 100%;
}
.tiparea {text-align: right;font-size: 12px;color: #333;width: 100%;
}
.tiparea a {color: #409eff;
}
</style>
5.创建接口login.ts
自定义方法和接口方法 对应注释的部分
import axios from '@/utils/http'// 注册接口
//接口方法
export function login(params: any) {return axios({url: '/api/v1/auth/register',method: 'post',headers: {'Content-Type': 'application/json;charset=UTF-8'},data: params})
}
//自定义方法
// export function login(params: any) {
// console.log(params)
// if(params.email=="123456" && params.password=="123456"){
// return true
// }else{
// return false
// }
// }
6.提交方法(引用ts)
对应注释的部分