vue3+ts+elementplus写一个登录页面教程

在这里插入图片描述

文章目录

  • 前言
    • 1. 安装 Vue CLI 和 TypeScript 支持
      • 2. 创建登录组件
  • 文章重点内容


前言

前期准备步骤:
创建一个使用 Vue 3 和 TypeScript 的登录页面涉及到多个步骤。以下是一个基本的教程,帮助你从头开始构建这样一个页面:

1. 安装 Vue CLI 和 TypeScript 支持

首先,你需要安装 Vue CLI 并配置它以支持 TypeScript。如果你还没有安装 Vue CLI,可以通过以下命令进行安装:

npm install -g @vue/cli  
# OR  
yarn global add @vue/cli

然后,你可以创建一个新的 Vue 3 项目并启用 TypeScript 支持:

vue create my-login-app

在创建过程中,选择 “Manually select features”,然后勾选 “TypeScript” 和其他你需要的特性(比如 Router、Linter/Formatter 等)。

2. 创建登录组件

在 src/views目录下创建一个新的 TypeScript 文件,比如 Login.vue。这个文件将包含你的登录表单和逻辑。

文章重点内容

页面样式:
在这里插入图片描述
页面代码:

		<div class="login-right-warp">
				<div class="login-right-warp-title">login</div>
				<div class="login-right-warp-form">
					<div class="login-right-warp-form_title">用户名登录</div>

					<el-form ref="ruleFormRef" style="max-width: 600px" :model="ruleForm" status-icon :rules="rules"
						label-width="auto" class="demo-ruleForm">
						<el-form-item prop="AccountNo">
							<el-input v-model="ruleForm.AccountNo" autocomplete="off" :prefix-icon="User"
								placeholder="请输入账号" />
						</el-form-item>
						<el-form-item prop="AccountPwd">
							<el-input v-model="ruleForm.AccountPwd" type="password" autocomplete="off" :prefix-icon="Lock"
								placeholder="请输入密码" />
						</el-form-item>
						<el-form-item prop="Code">
							<el-input v-model.number="ruleForm.Code" :prefix-icon="Promotion" class="login-content-code"
								placeholder="请输入验证码" />
							<span class="login-content-code-img" @click="generateCodeAsync()">{{ verificationCode.Code
							}}</span>
						</el-form-item>
						<el-form-item>
							<el-button type="primary" @click="submitForm(ruleFormRef)">登录</el-button>
						</el-form-item>
					</el-form>
					<div class="login-msg">* 温馨提示:建议使用谷歌、Microsoft Edge,版本 79.0.1072.62 及以上浏览器,360浏览器请使用极速模式</div>
				</div>
			</div>

script代码:

import { reactive, onMounted, ref } from 'vue';
import type { FormInstance, FormRules } from 'element-plus';
import { User, Lock, Promotion } from '@element-plus/icons-vue';
import { postLoginAsync, postGenerateCodeAsync } from '@/api/login';
import { useRouter } from 'vue-router';

// 使用 Vue Router 的 useRouter 函数来获取 router 实例
const router = useRouter();

const ruleFormRef = ref<FormInstance>();

// 页面加载时
onMounted(() => {
	generateCodeAsync();
});

const validateCodeKey = (rule: any, value: any, callback: any) => {
	if (value === '') {
		callback(new Error('请输入验证码'));
	} else {
		callback();
	}
};

const validateAccountNo = (rule: any, value: any, callback: any) => {
	if (value === '') {
		callback(new Error('请输入账号'));
	} else {
		callback();
	}
};
const validateAccountPwd = (rule: any, value: any, callback: any) => {
	if (value === '') {
		callback(new Error('请输入密码'));
	} else {
		callback();
	}
};

const ruleForm = reactive({
	AccountNo: '123',
	AccountPwd: '',
	CodeKey: '',
	Code: '',
});

const verificationCode = reactive({
	CodeKey: '',
	Code: '',
});



const rules = reactive<FormRules<typeof ruleForm>>({
	AccountNo: [{ validator: validateAccountNo, trigger: 'blur' }],
	AccountPwd: [{ validator: validateAccountPwd, trigger: 'blur' }],
	Code: [{ validator: validateCodeKey, trigger: 'blur' }],
});
const generateCodeAsync = () => {
	postGenerateCodeAsync().then((res: any) => {
		verificationCode.Code = res.Data.Code;
		verificationCode.CodeKey = res.Data.Key;
		ruleForm.CodeKey = res.Data.Key;
	});
};

const submitForm = (formEl: FormInstance | undefined) => {
	if (!formEl) return;
	formEl.validate((valid) => {
		if (valid) {
			console.log('submit!');
			router.push('/home');
		} else {
			console.log('error submit!');
			return false;
		}
	});
};
</script>

样式代码:

.login {
	width: 100vw;
	height: 100vh;
	background: #fff;

	.login-left {
		.login-left-logo {
			display: flex;
			align-items: center;
			position: absolute;
			top: 50px;
			left: 80px;
			z-index: 1;
			animation: logoAnimation 0.3s ease;

			img {
				width: 100px;
				height: 64px;
			}

			.login-left-logo-text {
				display: flex;
				flex-direction: column;
			}

			.login-left-logo-text span {
				margin-left: 10px;
				font-size: 30px;
				font-weight: 700;
				color: #de2910;
			}

			.login-left-logo-text .login-left-logo-text-msg {
				font-size: 12px;
				color: #de2910;
			}
		}

		.login-left-img {
			width: 90%;
			margin: 70px 0 0px 10%;
			height: 90%;
			min-height: 500px;
			min-width: 500px;
			display: flex;
			justify-content: center;
			align-items: center;

			img {
				height: 500px;
				min-width: 500px;
			}
		}
	}

	.login-right {
		width: 650px;

		.login-right-warp {
			border: 1px solid #e76959;
			border-radius: 3px;
			width: 500px;
			height: 550px;
			position: relative;
			overflow: hidden;
			background-color: #fff;
			margin: auto;

			.login-right-warp-title {
				height: 130px;
				line-height: 130px;
				font-size: 32px;
				font-weight: 800;
				text-align: center;
				animation: logoAnimation 0.3s ease;
				animation-delay: 0.3s;
				color: #f00;
			}

			.login-right-warp-form {
				padding: 0 50px 50px;
			}

			.login-right-warp-form_title {
				color: #de2910;
				width: 100%;
				padding: 10px 0px;
				border-bottom: 1px solid #e4e7ed;
				position: relative;
			}

			.login-right-warp-form_title::after {
				content: '';
				position: absolute;
				width: 90px;
				height: 2px;
				background: #de2910;
				bottom: 0;
				left: 0px;
			}
		}

		.el-form {
			margin-top: 30px;
		}

		.el-input {
			width: 100%;
			height: 40px;
		}

		.el-button {
			width: 100%;
			height: 40px;
			border-radius: 20px;
			background: #de2910;
			border: #de2910;
			margin: 20px 0px;
		}

		.login-content-code {
			width: 70%;
		}

		.login-content-code-img {
			width: 25%;
			background-color: #fff;
			border: 1px solid rgb(220, 223, 230);
			height: 38px;
			border-radius: 5px;
			margin-left: 4.5%;
			line-height: 38px;
			text-align: center;
			cursor: pointer;
		}

		.login-msg {
			margin-top: 30px;
			color: #a8abb2;
			font-size: 12px;
		}
	}
}

您好,我是肥晨。
欢迎关注我获取前端学习资源,日常分享技术变革,生存法则;行业内幕,洞察先机。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/502941.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ollama部署在线ai聊天

概述&#xff1a;虽然ollama在Windows方面还有很多bug&#xff0c;但不妨碍它在ai领域上面的成就 第一步&#xff1a;安装Ollama 官网&#xff1a;Download Ollama on Windows 下载安装即可。说明一下ollama的安装位置只能是c盘&#xff0c;好像改不了&#xff0c;但是数据模…

算法学习——LeetCode力扣动态规划篇8

算法学习——LeetCode力扣动态规划篇8 300. 最长递增子序列 300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; 描述 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删…

FA模型切换Stage模型之module的切换

从FA模型切换到Stage模型时&#xff0c;开发者需要将config.json文件module标签下的配置迁移到module.json5配置文件module标签下&#xff0c;具体差异见下列表格。 表1 FA模型module标签与Stage模型module标签差异对比 表2 FA模型metaData和Stage中metadata对比 表3 FA模型me…

【UI框架】——保姆式使用教程

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

深度学习500问——Chapter05: 卷积神经网络(CNN)(2)

文章目录 5.6 有哪些池化方法 5.7 1x1卷积作用 5.8 卷积层和池化层有什么区别 5.9 卷积核是否一定越大越好 5.10 每层卷积是否只能用一种尺寸的卷积核 5.11 怎样才能减少卷积层参数量 5.12 在进行卷积操作时&#xff0c;必须同时考虑通道和区域吗 5.13 采用宽卷积的好处有什么 …

多线程JUC 第2季 synchornized和Lock锁(重入,公平)

一 锁 1.1 锁的介绍 synchronized&#xff0c;和lock锁都是一种悲观锁。悲观锁适用于写多场景&#xff0c;乐观锁适用于读多场景&#xff0c;实现策略有&#xff1a;版本号和cas自旋算法。 1.2 类锁和对象锁的使用场景 1.3 任何对象都有一把锁 之所以任何一个对象都有把锁…

html第二次作业

骨架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, initi…

PyTorch深度学习快速入门(小土堆)

文章目录 16. 神经网络的基本骨架17.卷积操作18.卷积层 16. 神经网络的基本骨架 forward: import torch from torch import nnclass Tudui(nn.Module):def __init__(self):super().__init__()def forward(self,input):outputinput1return output#创建Tudui的实例对象 tuduiTu…

Django详细教程(二) - 部门用户管理案例

文章目录 前言一、新建项目二、新建app三、设计表结构四、新建数据库五、新建静态文件六、部门管理1.部门展示2.部门添加3.部门删除4.部门编辑 七、模板继承八、用户管理1.辨析三种方法方法一&#xff1a;原始方法方法二&#xff1a;Form组件(简便)方法三&#xff1a;ModelForm…

ARM-按键中断实验

代码 #include "stm32mp1xx_gic.h" #include "stm32mp1xx_exti.h" extern void printf(const char *fmt, ...); unsigned int i 0; void do_irq(void) {//获取要处理的中断的中断号unsigned int irqnoGICC->IAR&0x3ff;switch (irqno){case 99:pr…

前端工程师————HTML5学习

HTML5基础 开发工具很多&#xff0c;其中Hbulider较好用&#xff0c;下载网址如下&#xff1a; DCloud - HBuilder、HBuilderX、uni-app、uniapp、5、5plus、mui、wap2app、流应用、HTML5、小程序开发、跨平台App、多端框架 html表示整个页面 head表示搜素框 body表示内容 ti…

【蓝桥杯】矩阵快速幂

一.快速幂概述 1.引例 1&#xff09;题目描述&#xff1a; 求A^B的最后三位数表示的整数&#xff0c;A^B表示&#xff1a;A的B次方。 2&#xff09;思路&#xff1a; 一般的思路是&#xff1a;求出A的B次幂&#xff0c;再取结果的最后三位数。但是由于计算机能够表示的数字…

Gromacs模拟一:配体-双链蛋白质复合物体系准备

1、蛋白质的准备&#xff1a; 在RCSB网站下载想要的蛋白晶体&#xff08;教程里是3htb&#xff09;&#xff0c;用notepad等编辑器或是分子可视化软件除去里面的非蛋白分子或离子。 这里采用的是一个经过分子对接后的蛋白质pdb和配体小分子的pdb。 教程里提到的配体是2-丙基…

java算法day39 | 动态规划part02 ● 62.不同路径 ● 63. 不同路径 II

62.不同路径 思路&#xff1a; 本题非常巧妙。 第一步&#xff1a;定义一个dp数组存储到达每个位置的路径数。 第二步&#xff1a;每个位置的路径数它左面位置的路径数上面位置的路径数。 第三步&#xff1a;不好想的是如何初始化数组。 既然只能向下或向右走&#xff0c;可推出…

网络七层模型之会话层:理解网络通信的架构(五)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

浅谈AI未来发展趋势与挑战

对于AI大模型未来发展趋势与挑战的个人看法&#xff1a; 1、未来的发展趋势&#xff1a; AI大模型未来发展趋势可以从以下几个关键方面来讨论&#xff1a; 1. 能源与计算效率 绿色计算与节能技术&#xff1a;随着硬件技术的发展&#xff0c;预计未来的AI大模型将进一步降低能…

python电商结合双轨制

最近又重新整合翻看以前的数据&#xff0c;图片&#xff0c;绘画&#xff0c;还有各种编程代码&#xff0c;python,leetcode,还有关于商业方面的一些见解,想起了大学时候和同学们并肩作战&#xff0c;熬夜编码的时光。还有大数据&#xff0c;八爪鱼爬虫。 下面是我的手稿电商打…

Arduino通过Wire库读取AS5600编码器数据

Arduino通过Wire库读取AS5600编码器数据 ✨在实际测试中&#xff0c;测试AS5600除了使用径向磁铁之外&#xff0c;球型的或者正四方体的强磁铁&#xff0c;也是可以准确的测量角度。测试高度的话&#xff0c;从板子&#xff08;芯片引脚底部&#xff09;到磁铁底部15毫米内&…

算法打卡day21(开始回溯)

今日任务&#xff1a; 1&#xff09;77.组合 77.组合 题目链接&#xff1a;77. 组合 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;带你学透回溯算法-组合问题&#xff08;对应力扣题目&#xff1a;77…

Spring日志框架

前言 本文我们简单说说关于Spring中的日志框架,以及对应的注解 我们知道,公司服务器在运行的时候,一定会打印日志,有很多优点,比如预防报警,或者是某重大事故尝试修复等等都需要查看日志 应该说日志对我们来说并不陌生,我们在之前刷题或者是程序遇到bug的时候也经常会将程序的状…