网站首页 > 技术文章 正文
以前用react写过一个登录页面,不过实际工作中还是决定使用vue进行开发,这里就再记录一次用vue3实现一个登录页面。
演示准备
还是采用VSCode,暂时就个人感受来讲,免费的前端编程ide中,VSCode应该是首选。安装一下npm、pnpm,准备一些后端接口,可以用mock,或者随便找点后端框架写一点,我是用python flask在本地弄了一些需要的接口。
实操演示-创建工程
到工作目录打开cmd界面,通过命令新建一个vue项目工程:
npm create vue@latest
然后就是根据提示选择是否添加组件:
项目虽然创建成功了,但是里面是没有引入各种资源库的,需要通过命令安装一下:
此时可以通过命令启动这个新建的项目:
可以通过浏览器访问:
界面能正常显示出来,就表示项目创建成功。
实操演示-依赖库添加
先添加sass,这个库可以让我们更灵活的写css,我自己不算是前端开发,写css其实不是很频繁,但是看其他几个前端开发都挺喜欢用sass的。
通过命令添加:
再添加一个axios,这个是用来请求后端接口的:
最后再加一个element-plus,做这个登录页面,用不用element-plus都可以,可以根据自己喜好添加element-plus或者ant-design-vue都可以,都是类似功能的组件。
实操演示-清理不需要的内容
将新建项目时自动带入的一些组件、图片、样式文件等删除:
这些删除的文件在留存的代码中有对应的引用,也删除一下,可以通过运行项目,看哪边报错,找对应位置进行修改:
还有些比较复杂的,可以直接清除原内容,还原成一些基础代码,比如App.vue:
网上找一个reset.scss(npm的官网上就有),清除当前所有默认样式:
引用这个reset.scss:
这里的@路径别称是项目创建时自动配置的,可以在vite.config.ts中看到:
实操演示-静态结构搭建
如果刚开始没什么思路,可以到element-plus的官网上抄类似的代码:
只需要在外层配一个背景,改一下参数名称,其实就可以用了。
因为从element-plus上抄了代码,所以要配置对应的样式,和使用对应的组件:
我为了和后面登录效果做铺垫,先在App.vue中加一个路由组件:
因为要使用路由,所以要在main.tx中使用路由模块:
配置路由信息:
要写一个登录页面:
<script setup lang="ts">
import { ElMessage, type FormInstance, type FormRules } from 'element-plus';
import { ref, reactive } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter()
const url = ref('/images/favicon.ico')
const fit = 'scale-down'
const boxbg = ref('/images/login-box-bg.svg')
const form = reactive({
userName: '',
passWord: ''
})
const rules = reactive<FormRules>({
userName: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
passWord: [{ required: true, message: '请输入密码', trigger: 'blur' }]
})
const ruleFormRef = ref<FormInstance>()
const onSubmit = async (ruleFormRef: FormInstance | undefined) => {
if (!ruleFormRef) return;
await ruleFormRef.validate(async (valid, fields) => {
if (valid) {
// 这里要调用后端接口,根据后端返回的值,决定是否走后面的路由进入系统内部
router.push({ path: '/desktop' });
} else {
let errors: string = "";
fields?.userName?.forEach(element => {
errors += element.message + '; '
})
fields?.passWord?.forEach(element => {
errors += element.message + '; '
})
ElMessage({
type: "warning",
message: errors
})
}
})
}
</script>
<template>
<div class="login">
<div class="relative">
<div class="left">
<el-row>
<el-col :span="24">
<div class="homepageLogo">
<ul>
<li>
<el-image style="width: 50px; height: 40px;" :src="url" :fit="fit" />
</li>
<li><span>Allure System</span></li>
</ul>
</div>
</el-col>
</el-row>
<el-row>
<el-col>
<el-image class="boxgb" :src="boxbg" :fit="fit" />
<p class="p1">欢迎使用本系统</p>
<p class="p2">一个很潦草的后端管理系统</p>
</el-col>
</el-row>
</div>
<div class="right">
<el-row>
<el-col :span="24">
<h2>登录</h2>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form :model="form" label-width="120px" label-position="top" size="large" class="form"
:rules="rules" ref="ruleFormRef">
<el-form-item label="用户名" prop="userName">
<el-input v-model="form.userName"></el-input>
</el-form-item>
<el-form-item label="密码" prop="passWord">
<el-input v-model="form.passWord" type="password" show-password></el-input>
</el-form-item>
<el-form-item>
<el-button class="submitBtn" type="primary" @click="onSubmit(ruleFormRef)">登录</el-button>
</el-form-item>
</el-form>
</el-col>
</el-row>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.login {
width: 100%;
height: 100%;
.relative {
width: 100%;
height: 100%;
text-align: center;
.left {
width: 50%;
height: 100%;
float: left;
background-image: url('/images/login-bg.jpg');
.boxbg {
width: 350px;
height: 350px;
margin-top: 100px;
}
.homepageLogo {
height: 50px;
line-height: 50px;
margin-top: 40px;
margin-left: 40px;
span {
color: white;
font-size: 24px;
}
ul {
list-style: none;
li {
float: left;
margin-left: 5px;
}
}
}
p {
color: white;
}
.p1 {
font-size: 1.875rem;
line-height: 2.825rem;
}
.p2 {
font-size: 0.875rem;
line-height: 1.25rem;
}
}
.right {
width: 50%;
float: left;
padding-top: 15%;
.form {
width: 50%;
margin: 0px auto;
.submitBtn {
width: 100%;
}
}
}
}
}
</style>
实现效果就是这样:
实操演示-后端交互封装
使用axios封装一下filter.ts:
//导入axios
import axios from 'axios'
import { ElMessage } from 'element-plus'
//创建一个axios实例
const instance = axios.create({
withCredentials: true,
headers: {
'content-type': 'application/json,text/plain,*/*'
},
// withCredentials: true,
timeout: 5000 //5秒
})
instance.interceptors.request.use(
config => {
return config
},
error => {
ElMessage.error("遇到报错:", error)
}
)
//http 拦截器
instance.interceptors.response.use(
response => {
console.log(response.data)
//拦截请求,统一相应
if (response.data.isSuccess) {
return response.data.result
} else {
ElMessage.error(response.data.msg)
return response.data.result
}
},
//error也可以处理
error => {
console.log(error)
if (error.response) {
switch (error.response.status) {
case 401:
ElMessage.warning("资源没有访问权限!")
break
case 404:
ElMessage.warning("接口不存在,请检查接口地址是否正确!")
break
case 500:
ElMessage.warning("内部服务器错误,请联系系统管理员!")
break
default:
return Promise.reject(error.response.data) // 返回接口返回的错误信息
}
}
else {
ElMessage.error("遇到跨域错误,请设置代理或者修改后端允许跨域访问!")
}
}
)
export default instance
在根据上面封装的filter.ts,写一下获取token的请求:
//需要拦截器的地方使用instance对象, 有自定义返回逻辑的地方沿用axios,在组件内部处理返回结果即可
import instance from './filter'
const http = "/api";
//获取token
export const getToken = (name: string, password: string) => {
return instance.get(http + "/Login/GetToken?name=" + name + "&password=" + password);
}
应该会遇到跨域问题,所以上面没有写具体url,到vite.config.ts中配置代理:
回到LoginPage.vue,调用getToken方法:
这个token是我随便写的,正常的需要经过一些转换才能读取其中的信息。
如果token中还有其他信息,也可以存储到本地cookie中,当然如果token要被经常使用到,也可以直接将token持久化,比如这样:
总结
一个潦草的登录模块就这样做好了。当然一个完整的登录模块,还有很多鉴权、路由控制等很多功能,这里就不展开了。
猜你喜欢
- 2025-01-21 SpringBoot与Vue交互解决跨域问题「亲测已解决」
- 2025-01-21 细解跨域以及跨域的解决方案
- 2025-01-21 52、Vue 怎么实现跨域(必会)
- 2025-01-21 聊聊axios-axios的介绍以及请求方式
- 2025-01-21 跨域请求如何携带cookie?不小心都拿了Offer
- 2025-01-21 前后端分离session问题
- 2025-01-21 springboot+security后端与前端需要注意的withCredentials设置
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)