Vue学习二——创建登录页面

前言

以一个登录页面为例子,这篇文章简单介绍了vue,element-plus的一些组件使用,vue-router页面跳转,pinia及持久化存储,axios发送请求的使用。后面的页面都大差不差,也都这么实现,只是内容,页面布局会变一些。其他插件功能,用到再介绍。

一、实现效果图

在这里插入图片描述

  1. 一个大的div,class=main
  2. 在main这个div中,有一个div,class=“login_box”
  3. login_box中,分上面部分,包含icon和标题;下面部分就是登录表单数据
<template><div class="main"><div class="login_box">		<div class="head"></div><div class="login-form" ></div></div></div>
</template>

二、页面内容

1.main

main只需要铺满整个页面,给个背景图就行。得到一个铺满页面的图片

.main{width: 100vw;height: 100vh;background: url('../../assets/bg.jpeg');background-size: cover;}

2.login_box

.login_box{width: 500px;height: 460px;box-shadow:  0 0 5px var(--el-color-primary);position:absolute;top:calc(50vh - 230px);left: calc(50vw - 250px);border-radius: 20px;background-color: rgba(255, 255, 255, 0.8);}

在这里插入图片描述

3. login_box -> head

<div class="head"><img src="@/assets/logo.jpeg" alt="logo" class="logo"><div class="title">接口自动化平台</div>
</div>
.head{display: flex;justify-content: center;align-items: center;height: 150px;.logo{width: 60px;height: 60px;border-radius: 50px;}.title{font-size: 30px;font-weight: bold;color: var(--el-color-primary);margin-left: 20px;}}

在这里插入图片描述
4. login_box -> login_form

<div class="login-form" ><el-form :model="loginForm"><el-form-item ><el-input prefix-icon="User" v-model="loginForm.username" placeholder="请输入用户名"/></el-form-item><el-form-item ><el-input type="password" prefix-icon="Lock" v-model="loginForm.password" placeholder="请输入密码"/></el-form-item><el-form-item><el-switch v-model="loginForm.status" inactive-text='记住登录状态' /></el-form-item><el-form-item><el-button  type="primary"  @click="LoginSubmit(loginFormRef)" style="width: 100%;">登 录</el-button></el-form-item><el-link @click="router.push('register')" type="primary">没有账号?点击注册</el-link></el-form>
</div>
.login-form{margin: 0 30px;}

在这里插入图片描述

三、数据绑定

1. 动态数据绑定

使用 v-bind:(可以简写为:) 来进行动态数据绑定,

例如:将这里的登录按钮,是否可以点击设计为只有用户名和密码都不空才能点击。

可以设置disable属性,给这个属性动态绑定一个值‘canClick’,这个值是计算出来的

<el-form-item><el-button :disabled='canClick' type="primary"  @click="LoginSubmit(loginFormRef)" style="width: 100%;">登 录</el-button>
</el-form-item>// 未输入账号密码禁用登录
const canClick = computed(()=>{if (loginForm.username!=='' && loginForm.password!==''){return false}else{return true}})

计算属性computed

此时,没有输入账号密码,登录按钮就不能点击了。
在这里插入图片描述

更多关于计算属性可以参考: vue官网-计算属性

2. 双向绑定

v-model=" " 这样进行数据双向绑定
 <el-input type="password" prefix-icon="Lock" v-model="loginForm.password" placeholder="请输入密码"/>
...
<script setup>
const loginForm = reactive({username:"",password:"",status:true	
})
</script>

将input输入框的内容与loginForm.password双向绑定。

3. 响应式数据

ref 和 reactive 我自己理解来说,就是ref定义简单一个具有响应性类型数据,比如字符串,布尔值,数值。而reactive可以定义复合的内容。在更改他们值的时候,页面显示也会同时更改

他们区别简单来说,就是reactive只存储对象,而ref存储基本数据类型,比如数字、字符串等。
更多可以参考其他文档,这里不主要介绍这块,因为我自己也不是很懂,平时拿来简单用用就是了,没深入了解过。嘿嘿

ref和reactive官网介绍
ref和reactive区别

四、Element表单数据校验

elment-plus表单校验

1. 创建表单校验规则

Form 组件提供了表单验证的功能,只需为 rules 属性传入约定的验证规则,并将 form-Item 的 prop 属性设置为需要验证的特殊键值即可

	//表单校验规则const loginRules = reactive({username: [{ required: true, message: '账号不能为空', trigger: 'blur' },{ min: 4, max: 18, message: '账号长度4-18位', trigger: 'blur' },],password :[{ required: true, message: '密码不能为空', trigger: 'blur' },{ min: 6, max: 18, message: '密码长度6-18位', trigger: 'blur' },]})

2. 给Form组件加上规则

< el-form model="loginForm" :rules="loginRules" >

3. 将 form-item 的 prop 属性设置为需要验证的特殊键值

例如:

<el-form-item prop="username"><el-input prefix-icon="User" v-model="loginForm.username" placeholder="请输入用户名"/>
</el-form-item><el-form-item prop="password"><el-input type="password" prefix-icon="Lock" v-model="loginForm.password" placeholder="请输入密码"/>
</el-form-item>

校验规则是光标移出输入框校验,所以没有输入用户名,点到密码。就会提示自定义的校验规则内容
在这里插入图片描述

五、发送请求(后端接口使用之前fastapi项目)

在api/module/UserApi.js里,定义所有用户相关的接口

1. 用户登录模块接口

// api/module/UserApi.js
import request from "@/api/request";//导出请求方法
export default {//登录loginApi(data){return request.post('/api/users/login/',data)},
}

在这里插入图片描述

这个接口是之前fastapi栏写的,这里直接用。
在这里插入图片描述

2. 使用表单引用对象

在点击登录时,将表单引用对象传过去。首先进行表单预校验,预校验通过后,再调用接口,这样不会浪费资源

<el-form :model="loginForm" :rules="loginRules" ref='loginFormRef'>
......
<el-form-item><el-button :disabled='canClick' type="primary"  @click="LoginSubmit(loginFormRef)" style="width: 100%;">登 录</el-button>
</el-form-item><script setup>import http from '@/api/index'...const loginFormRef=ref(null)...const LoginSubmit = async(loginRef)=>{//表单预校验await loginRef.validate(async (valid)=>{if(valid){const response = await http.user.loginApi(loginForm)if(response.status === 200){ElNotification({title: '登录成功',message: '您已登录成功,进入首页',type: 'success',duration: 3,})}else{ElMessage({message: response.data.detail,type: 'error',duration: 3,})}}})}
</script>

elemet-plus通知消息弹窗

为了页面效果更美观,点击后得到反馈结果。使用了这个消息弹窗

import { ElNotification,ElMessage} from 'element-plus'

Feedback 反馈组件

3. 发送请求(跨域问题)

在这里插入图片描述
能看到这里发送请求成功了,前端请求这块是没问题了。
应该是跨域配置有问题,一般是服务端配置问题。
重新配置了一下服务端,现在可以正常访问了。

# pyhton服务端
origins = ['http://127.0.0.1:5173',"http://localhost:5173"]app.add_middleware(CORSMiddleware,allow_origins=origins,allow_credentials=True,allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],allow_headers=["*"],
)

在这里插入图片描述

六、pinia数据持久化

1. 下载pinia-plugin-persist

npm install pinia-plugin-persist

2.注册插件

//main.jsimport { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'// 创建一个pinia
const pinia = createPinia()// 将持久化的插件注册到pinia中
pinia.use(piniaPluginPersist)app.use(pinia)

3.在store中设置

在store下创建UserStore.js用来存储用户相关的信息,
使用localStorage来存储数据,也可以使用sessionStorage,看个人需求。

  • localStorage:数据的持久化程度高,即使用户关闭浏览器后,数据依然会被保留。除非显式删除,数据可以一直存在,适用于持久保存用户偏好设置、用户认证信息等需要长时间保存的数据。
  • sessionStorage:数据仅在浏览器的会话期间有效。一旦关闭页面或标签页,数据就会被清除,适用于存储临时性的数据,如表单状态、页面之间的传递数据等。

在这里插入图片描述

import {defineStore} from 'pinia'export const UserStore = defineStore('ustore',{//全局数据state:()=>{return {token:null,userinfo:null,isLogin:false}},// 定义持久化配置persist:{enabled:true,strategies:[{key:'userInfo',storage:localStorage}]}})

4. 在需要用到的地方进行使用

以登录成功为例,登录后保存用户token和用户信息。

//LoginView.vueimport{UserStore} from '@/stores/UserStore'//创建用户store对象
const uStore = UserStore()
...LoginSubmit()=>{...
...
//登录成功后保存用户信息//保存用户token和用户信息uStore.token = response.data.tokenuStore.userinfo = response.data.user// 修改认证状态if(loginForm.status){uStore.isLogin = true}}

最开始localStorage没有存储数据
在这里插入图片描述
登录成功后,就把数据记录下来了key:'userInfo'
在这里插入图片描述

七、页面跳转及其他页面使用pinia存储的数据

实现一个功能:登录成功后,需要跳转首页,首页展示token信息。

1. 创建一个home页面

在这里插入图片描述

2. 注册路径

在router/index中注册home的路径
在这里插入图片描述

3. 登录成功跳转

在登录页面,进行跳转

import {useRouter} from 'vue-router'//创建路由对象
const router = useRouter()...
//登录成功,跳转home页面router.push({name:"home"})

在这里插入图片描述

项目相关部分代码

LoginView.vue

<template><div class="main"><div class="login_box">		<div class="head"><img src="@/assets/logo.jpeg" alt="logo" class="logo"><div class="title">接口自动化平台</div></div><div class="login-form" ><el-form :model="loginForm" :rules="loginRules" ref='loginFormRef'><el-form-item prop="username"><el-input prefix-icon="User" v-model="loginForm.username" placeholder="请输入用户名"/></el-form-item><el-form-item prop="password"><el-input type="password" prefix-icon="Lock" v-model="loginForm.password" placeholder="请输入密码"/></el-form-item><el-form-item><el-switch v-model="loginForm.status" inactive-text='记住登录状态' /></el-form-item><el-form-item><el-button :disabled='canClick' type="primary"  @click="LoginSubmit(loginFormRef)" style="width: 100%;">登 录</el-button></el-form-item><el-link @click="router.push('register')" type="primary">没有账号?点击注册</el-link></el-form></div></div></div>
</template><script setup>import {reactive,ref,computed} from 'vue'import http from '@/api/index'import { ElNotification,ElMessage} from 'element-plus'import{UserStore} from '@/stores/UserStore'import {useRouter} from 'vue-router'//创建路由对象const router = useRouter()//创建用户store对象const uStore = UserStore()const loginFormRef=ref(null)const loginForm = reactive({username:"",password:"",status:true	})const canClick = computed(()=>{if (loginForm.username!=='' && loginForm.password!==''){return false}else{return true}})//表单校验规则const loginRules = reactive({username: [{ required: true, message: '账号不能为空', trigger: 'blur' },{ min: 4, max: 18, message: '账号长度4-18位', trigger: 'blur' },],password :[{ required: true, message: '密码不能为空', trigger: 'blur' },{ min: 6, max: 18, message: '密码长度6-18位', trigger: 'blur' },]})const LoginSubmit = async(loginRef)=>{console.log('click!!!')//表单预校验await loginRef.validate(async (valid)=>{if(valid){const response = await http.user.loginApi(loginForm)if(response.status === 200){ElNotification({title: '登录成功',message: '您已登录成功,进入首页',type: 'success',duration: 3000,})//保存用户token和用户信息uStore.token = response.data.tokenuStore.userinfo = response.data.user// 修改认证状态if(loginForm.status){uStore.isLogin = true}// 跳转到home页面router.push({name:"home"})}else{ElMessage({message: response.data.detail,type: 'error',duration: 3,})}}})}
</script><style scoped lang='scss'>.main{width: 100vw;height: 100vh;/* background: url('../assets/hz.svg'); */background: url('../../assets/bg.jpeg');background-size: cover;.login_box{width: 500px;height: 460px;box-shadow:  0 0 5px var(--el-color-primary);position:absolute;top:calc(50vh - 230px);left: calc(50vw - 250px);border-radius: 20px;background-color: rgba(255, 255, 255, 0.8);}.head{display: flex;justify-content: center;align-items: center;height: 150px;.logo{width: 60px;height: 60px;border-radius: 50px;}.title{font-size: 30px;font-weight: bold;color: var(--el-color-primary);margin-left: 20px;}}.login-form{margin: 0 30px;}}</style>

stores/UserStore.js

import {defineStore} from 'pinia'export const UserStore = defineStore('ustore',{//全局数据state:()=>{return {token:null,userinfo:null,isLogin:false}},// 定义持久化配置persist:{enabled:true,strategies:[{key:'userInfo',storage:localStorage}]}})

router/index.js

import { createRouter, createWebHistory } from 'vue-router'
// import HomeView from '../views/HomeView.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path:'/',redirect:'/login'},{path: '/login',name: 'login',component: () => import('../views/User/LoginView.vue'),},{path: '/home',name: 'home',component: () => import('../views/Home/HomeView.vue'),},], 
})export default router

main.js

import './assets/main.css'import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPluginPersist from 'pinia-plugin-persist'import App from './App.vue'
import router from './router'import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'//语言国际化
import zhCn from 'element-plus/es/locale/lang/zh-cn'//icon组件
import * as ElementPlusIconsVue from '@element-plus/icons-vue'const app = createApp(App)//注册element-plus语言国际化
app.use(ElementPlus, {locale: zhCn,
})//注册elemnt-plus的icon组件
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}// 创建一个pinia
const upinia = createPinia()// 将持久化的插件注册到pinia中
upinia.use(piniaPluginPersist)app.use(upinia)
app.use(router)app.mount('#app')

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ZYNQ初识10(zynq_7010)UART通信实验

基于bi站正点原子讲解视频&#xff1a; 系统框图&#xff08;基于串口的数据回环&#xff09;如下&#xff1a; 以下&#xff0c;是串口接收端的波形图&#xff0c;系统时钟和波特率时钟不同&#xff0c;为异步时钟&#xff0c;&#xff0c;需要先延时两拍&#xff0c;将时钟同…

java小知识点总结

一、比特流的本质就是数组 二、位运算 位运算就是CPU的底层原理&#xff0c;半导体电路进行位运算 位运算涉及一些算法&#xff0c;&和^ ^ 异或 两变量交换值&#xff0c;不依赖第三个变量 x^s k 异或知道两者就能推另一个 a a<<2就是乘以2的多少次方 相反 a…

vue3后台系统动态路由实现

动态路由的流程&#xff1a;用户登录之后拿到用户信息和token&#xff0c;再去请求后端给的动态路由表&#xff0c;前端处理路由格式为vue路由格式。 1&#xff09;拿到用户信息里面的角色之后再去请求路由表&#xff0c;返回的路由为tree格式 后端返回路由如下&#xff1a; …

贪心算法笔记

贪心算法笔记 大概内容 贪心就是对于一个问题有很多个步骤,我们在每一个步骤中都选取最优的那一个,最后得出答案。就是在一些函数中可行,但是有些比如二次函数,因为它的转折点不一定最优,就是不可行的。那么如何判断贪心呢?有这么几种 看时间复杂度,一般的就是 O ( n…

CVE-2025-22777 (CVSS 9.8):WordPress | GiveWP 插件的严重漏洞

漏洞描述 GiveWP 插件中发现了一个严重漏洞&#xff0c;该插件是 WordPress 最广泛使用的在线捐赠和筹款工具之一。该漏洞的编号为 CVE-2025-22777&#xff0c;CVSS 评分为 9.8&#xff0c;表明其严重性。 GiveWP 插件拥有超过 100,000 个活跃安装&#xff0c;为全球无数捐赠平…

ubuntu官方软件包网站 字体设置

在https://ubuntu.pkgs.org/22.04/ubuntu-universe-amd64/xl2tpd_1.3.16-1_amd64.deb.html搜索找到需要的软件后&#xff0c;点击&#xff0c;下滑&#xff0c; 即可在Links和Download找到相关链接&#xff0c;下载即可&#xff0c; 但是找不到ros的安装包&#xff0c; 字体设…

细说STM32F407单片机以DMA方式读写外部SRAM的方法

目录 一、工程配置 1、时钟、DEBUG、GPIO、CodeGenerator 2、USART3 3、NVIC 4、 FSMC 5、DMA 2 &#xff08;1&#xff09;创建MemToMem类型DMA流 &#xff08;2&#xff09;开启DMA流的中断 二、软件设计 1、KEYLED 2、fsmc.h、fsmc.c、dma.h、dma.c 3、main.h…

二分查找算法——山脉数组的峰顶索引

一.题目描述 852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 二.题目解析 题目给了我们一个山脉数组&#xff0c;山脉数组的值分布就如下面的样子&#xff1a; 然后我们只需要返回数组的峰值元素的下标即可。 三.算法原理 1.暴力解法 因为题目明确说明…

重塑视频创作的格局!ComfyUI-Mochi本地部署教程

一、介绍 mochi是近期Genmo公司开源的先进视频生成模型&#xff0c;具有高保真运动和强大的提示遵循性。此模型的发布极大的缩小了闭源和开源视频生成系统之间的差距。 目前&#xff0c;视频生成模型与现实之间存在巨大差距。其中最影响视频生成的两个关键功能也就是运动质量和…

Docker 安装开源的IT资产管理系统Snipe-IT

一、安装 1、创建docker-compose.yaml version: 3services:snipeit:container_name: snipeitimage: snipe/snipe-it:v6.1.2restart: alwaysports:- "8000:80"volumes:- ./logs:/var/www/html/storage/logsdepends_on:- mysqlenv_file:- .env.dockernetworks:- snip…

Oracle重启后业务连接大量library cache lock

一、现象 数据库和前段应用重启后&#xff0c;出现大量library cache lock等待事件。 二、分析解决 本次异常原因是&#xff1a;原因定位3&#xff1a; 库缓存对象无效 Library cache object Invalidations 三、各类情况具体分析如下 原因定位1&#xff1a;由于文字导致的非…

硬件设计-七位半电压表硬件方案(下)

目录 摘要 简介 解决方案和评估系统简介 应用聚焦&#xff1a;高准确度数据采集器 结论 摘要 本文探讨了为仪器仪表应用设计高准确度设备所涉及的挑战&#xff0c;并介绍了由低INL SAR ADC、全集成式超低温漂精密基准电压源、四通道匹配电阻网络和零漂移低噪声放大器构建的…

基于springboot+vue+微信小程序的宠物领养系统

基于springbootvue微信小程序的宠物领养系统 一、介绍 本项目利用SpringBoot、Vue和微信小程序技术&#xff0c;构建了一个宠物领养系统。 本系统的设计分为两个层面&#xff0c;分别为管理层面与用户层面&#xff0c;也就是管理者与用户&#xff0c;管理权限与用户权限是不…

Termora 一个开源的 SSH 跨平台客户端工具

Termora 是一个终端模拟器和 SSH 客户端&#xff0c;支持 Windows&#xff0c;macOS 和 Linux。 功能特性 支持 SSH 和本地终端支持 SFTP 文件传输支持 Windows、macOS、Linux 平台支持 Zmodem 协议支持 SSH 端口转发支持配置同步到 Gist支持宏&#xff08;录制脚本并回放&…

TypeScript Jest 单元测试 搭建

NPM TypeScript 项目搭建 创建目录 mkdir mockprojectcd mockproject初始化NPM项目 npm init -y安装TypeScript npm i -D typescript使用VSCode 打开项目 创建TS配置文件tsconfig.json {"compilerOptions": {"target": "es5","module&…

sql模糊关联匹配

需求目标&#xff1a; 建立临时表 drop table grafana_bi.zbj_gift_2024;USE grafana_bi; CREATE TABLE zbj_gift_2024 (id INT AUTO_INCREMENT PRIMARY KEY,userName VARCHAR(255),giftName VARCHAR(255),giftNum INT,points INT,teacher VARCHAR(255),sendDate DATETIME,…

Web前端:JavaScript标识符与变量

JavaScript介绍 JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”&#xff0c;指的是它不具备开发操作系统的能力&#xff0c;而是只用来编写控制其他大型应用程序的“脚本”。 JavaScript 是一种嵌入式&#xff08;embedded&#xff09;语言。它本身提供的核心语法不算…

mac homebrew配置使用

本文介绍mac上homebrew工具的安装、配置过程。homebrew功能类似于centos的yum&#xff0c;用于软件包的管理&#xff0c;使用上有命令的差异。 本次配置过程使用mac&#xff0c;看官方文档&#xff0c;在linux上也可以用&#xff0c;但我没试过&#xff0c;有兴趣的同学可以试试…

对话新晋 Apache SeaTunnel Committer:张圣航的开源之路与技术洞察

近日&#xff0c;张圣航被推选为 Apache SeaTunnel 的 Committer成员。带着对技术的热情和社区的责任&#xff0c;他将如何跟随 Apache SeaTunnel 社区迈向新的高度&#xff1f;让我们一起来聆听他的故事。 自我介绍 请您简单介绍一下自己&#xff0c;包括职业背景、当前的工作…

智慧公厕大数据驱动下的公共卫生管理与优化

在快速发展的城市化进程中&#xff0c;公共卫生问题日益凸显&#xff0c;成为城市管理的重要议题。智慧公厕&#xff0c;作为公共卫生设施的一次革命性创新&#xff0c;正借助物联网技术的东风&#xff0c;引领公共卫生进入一个全新的生态时代。本文将深入探讨智慧公厕如何利用…