ACM设计平台-核心模块解析-赵家康
负责模块解析-赵家康
一、Login.vue
功能逻辑、数据绑定、表单验证、与后端交互 Vue 登录页面的代码设计
代码功能概览
代码实现了一个典型的登录页功能,核心包括:
-
表单输入(学号、用户名、密码、验证码)
-
验证码生成与校验
-
勾选用户协议
-
表单提交并与后端接口
/api/login
通信 -
根据后端返回信息执行不同响应处理
-
登录成功后存储用户信息并跳转主页
前端登录模块技术文档
一、组件概述
该组件为前端登录页面的核心逻辑模块,使用 Vue 2 编写,基于 axios
实现与后端 API 的通信,完成用户的登录验证功能。包含用户输入验证、验证码生成、后端登录接口调用、用户状态保存等功能。
二、组件定义
export default {name: 'Login',... }
定义组件名称为 Login
,该组件在整个系统中负责处理用户登录请求。
三、数据结构(data()
)
data() {return {student_id: '', // 学号username: '', // 用户名password: '', // 密码verify: '', // 用户输入的验证码verify_number: '', // 系统生成的验证码agreed: false // 是否勾选用户协议} }
说明:
-
所有字段均通过
v-model
实现数据双向绑定。 -
字段设计简单,适合教学或基础项目使用。
四、生命周期钩子(mounted()
)
mounted(){this.randomCode(); }
页面加载时自动生成一个验证码,通过 randomCode()
方法实现。
五、方法说明(methods
)
1. login() 登录主逻辑(核心功能)
async login() {try {if (!this.judge()) {this.refresh();return;} const formData = new URLSearchParams();formData.append('student_id', this.student_id);formData.append('username', this.username);formData.append('password', this.password); const response = await this.$axios.post('/api/login', formData, {headers: { 'Content-Type': 'application/x-www-form-urlencoded' },timeout: 5000});if (response.data.success) {this.$message.success('登录成功');const user = {student_id: this.student_id,username: this.username,password: this.password,flag: true};sessionStorage.setItem('user', JSON.stringify(user));this.refresh();this.$router.push('/');} else {// 根据后端返回状态码进行提示if (response.data.status === 0) {this.$message.error('该学号尚未注册');} else if (response.data.status === 2) {this.$message.error('密码错误');} else if (response.data.status === -1) {this.$message.error('服务器错误,请稍后重试');}}} catch (error) {this.$message.error('登录失败,请稍后重试');console.error('完整错误信息:', error);} }
特点:
-
使用
axios
以x-www-form-urlencoded
形式向后端发送登录请求。 -
支持错误捕获和超时设置,提升用户体验。
-
登录成功后,将用户信息保存至
sessionStorage
,并跳转主页。
2. judge() 表单校验
judge(){if (!this.agreed) {this.$message.error('请同意用户协议');return false;}if (this.username === '' || this.password === '' || this.confirm_password === '' || this.verify === '') {this.$message.error('请输入完整信息');return false;}if (this.verify !== this.verify_number) {this.$message.error('验证码错误');this.randomCode();return false;}return true; }
存在的问题:
-
this.confirm_password
在data()
中未定义,也不属于登录逻辑,应删去该判断。 -
没有利用
element-ui
的表单校验规则,而是手写逻辑判断。
3. randomCode() 验证码生成
randomCode() {this.verify_number = Math.floor(1000 + Math.random() * 9000).toString();// 背景颜色变化用于验证码按钮美化 }
功能说明:
-
每次调用会生成一个新的 4 位数字验证码。
-
将验证码值保存至
verify_number
,用于后续校验。 -
验证码背景色随机变化,提升页面视觉体验(无图像识别功能,仅限于防误输入)。
4. refresh() 表单重置
refresh() {this.student_id = '';this.username = '';this.password = '';this.verify = '';this.verify_number = '';this.agreed = false;this.randomCode(); }
功能说明:
-
清除所有输入数据并重新生成验证码。
-
在登录失败或初次进入页面时调用。
六、与后端的交互接口
接口调用:
this.$axios.post('/api/login', formData, { ... });
请求方式:
-
POST
-
表单编码方式为:
application/x-www-form-urlencoded
请求参数:
参数名 | 类型 | 含义 |
---|---|---|
student_id | String | 学号 |
username | String | 用户名 |
password | String | 密码 |
响应结构(后端设计建议):
{"success": true,"status": 1,"message": "登录成功" }
字段 | 含义 |
---|---|
success | 是否成功 |
status | 状态码(0:未注册, 2:密码错, -1:服务异常) |
message | 描述信息 |
七、登录态管理
sessionStorage.setItem('user', JSON.stringify(user));
说明:
-
前端将用户信息临时保存在
sessionStorage
中。 -
user.flag = true
表示已登录。 -
安全性一般,推荐实际项目中使用 token 和后端验证配合实现登录态。
八、安全性与优化建议
问题 | 建议 |
---|---|
明文密码存储 | 不建议存密码,可用 token 或标志位 |
验证码仅前端生成 | 可考虑后端图形验证码 |
表单校验不健壮 | 应使用 el-form 的 rules 验证机制 |
confirm_password 多余 | 删除该字段判断 |
缺少网络错误细分提示 | 根据错误类型(超时、断网、500等)细化提示 |
九、结语
该登录模块是一个完整的、功能清晰的前端登录实现,适用于教学与小型项目。可进一步增强安全性、校验性与用户体验,例如添加:
-
CSRF 保护机制
-
图形验证码
-
token 登录
-
后端 JWT 验证等
Vue 注册组件脚本 的逐行讲解
模块导出
<script> export default {
这是 Vue 单文件组件的标准语法,导出一个组件对象。这样它就可以在其他文件中被导入和使用。
name 与 data
name: 'Login',data() {return {student_id:'',username:'',password:'',confirm_password:'',verify:'',verify_number:'',agreed:false,}},
功能说明:
-
name
定义组件名称为'Login'
(建议此处改为'Register'
更合理)。 -
data()
返回组件状态数据(响应式):-
student_id
: 学号输入 -
username
: 用户名 -
password
: 密码输入 -
confirm_password
: 确认密码输入 -
verify
: 用户输入的验证码 -
verify_number
: 系统生成的验证码(字符串) -
agreed
: 是否勾选同意用户协议(布尔值)
-
在 Vue.js 中,data() 是一个非常重要的概念,它定义了组件的“状态数据” 1. 组件状态数据 组件状态数据是指组件内部存储的、用于控制组件行为和渲染结果的变量。这些变量通常存储在组件的 data() 函数中,它们是组件的“内部状态”。 作用: 控制渲染:组件的模板(<template>)会根据这些状态数据来渲染页面内容。 存储用户输入:例如,用户在表单中输入的内容可以存储在状态数据中。 控制逻辑:例如,布尔值可以用于控制是否显示某个元素。 2. 响应式 Vue 的核心特性之一是“响应式系统”。响应式意味着当组件的状态数据发生变化时,Vue 会自动检测到这些变化,并更新页面上的内容。 如何实现: Vue 会将 data() 中定义的变量转换为响应式对象。当这些变量的值发生变化时,Vue 的响应式系统会触发视图的更新。 3. data() 的作用 data() 是一个函数,它返回一个对象。这个对象中的每个属性都是组件的状态数据,并且是响应式的。 为什么是函数而不是对象: 在 Vue 中,data 必须是一个函数,而不是直接写成对象。这是因为 Vue 需要为每个组件实例创建独立的状态数据,而不是共享同一个对象。 如果直接写成对象,所有组件实例会共享同一个状态数据,这会导致数据冲突。
mounted 生命周期钩子
mounted(){this.randomCode();},
-
页面初次加载时,调用
randomCode()
自动生成验证码。 -
确保验证码初始化完成。
methods 方法
methods: {
定义所有方法逻辑,供模板中的按钮/事件绑定调用。
async register()
注册主逻辑
async register() {
使用 async/await
编写异步方法,完成用户注册流程。
1. 表单验证
if(!this.judge()){this.refresh();return;}
-
先执行
judge()
校验用户输入是否合规。 -
如果不合法则清空输入并终止注册流程。
2. 构造 form 数据
const formData = new URLSearchParams();formData.append('student_id', this.student_id);formData.append('username', this.username);formData.append('password', this.password);
-
创建
application/x-www-form-urlencoded
的请求体。 -
添加三个表单字段:学号、用户名、密码。
3. 清空用户输入(防止脏数据)
this.refresh();
-
在发出请求前先清空输入框(也可以改为成功后清空)。
4. 发起 HTTP POST 请求
const response = await this.$axios.post('/api/userc?action=register', formData, {timeout: 5000});
-
调用后端接口
/api/userc?action=register
发起注册请求。 -
设置超时为 5 秒,避免接口卡顿导致页面无响应。
5. 处理返回结果
if (response.data.success) {this.$message.success('注册成功');this.$router.push('/login');} else {this.$message.error(response.data.message || '注册失败');}
-
成功:弹出成功消息,并跳转到登录页面。
-
失败:显示后端返回的错误信息或默认提示。
6. 错误捕获处理
} catch (error) {this.$message.error('注册失败,请稍后重试');console.error('完整错误信息:', error);}
-
捕获异常(如网络错误),并输出调试日志。
-
避免程序中断。
randomCode()
验证码生成器
randomCode() {this.verify_number = Math.floor(1000 + Math.random() * 9000).toString()
-
生成一个 4 位数字验证码并存入
verify_number
。
let change=((Math.ceil(Math.random()*10))+100)%4;let rgb1=(Math.ceil(Math.random()*1000)%256);let rgb2=(Math.ceil(Math.random()*1000)%256);let rgb3=(Math.ceil(Math.random()*1000)%256);
-
生成随机背景色,用于验证码背景美化。
let v=document.querySelector('.verify_code');
-
获取页面上类名为
verify_code
的 DOM 元素。
if(change==0)v.style.background=`linear-gradient(to bottom right,rgb(${rgb1},${rgb2},${rgb3}),black)`else if(change==1)v.style.background=`linear-gradient(to top right,rgb(${rgb1},${rgb2},${rgb3}),black)`...
-
应用不同方向的渐变背景样式。
-
- `Math.random() * 10` 得到0到10的随机数,`Math.ceil`向上取整,范围1~10。 - 加上100后对4取余,得到0、1、2、3中的一个。 - 这个 `change` 是用来随机决定渐变背景的方向,4种方向随机选一个。
judge()
表单输入校验函数
judge(){
用于在注册前判断用户输入是否有效。
if(!this.agreed){this.$message.error('请同意用户协议'); return false;}
必须勾选协议才能注册。
if(this.username==''||this.password==''||this.confirm_password==''||this.verify==''||this.student_id==''){this.$message.error('请输入完整信息');return false; }
所有输入项必须填写。
if(this.password!=this.confirm_password){this.$message.error('两次密码输入不一致');return false; }
确认密码必须一致。
if(this.verify!=this.verify_number){this.$message.error('验证码错误');this.randomCode(); return false;}
用户输入的验证码必须与系统生成的一致。
let student_id_reg = /^\d{9}$/;if(!student_id_reg.test(this.student_id)){this.$message.error('学号必须符合要求');return false;}
学号必须是9位数字。
let reg=/^[a-zA-Z0-9]{6,16}$/;if(!reg.test(this.password)){this.$message.error('密码格式错误');return false;}
密码必须为6~16位字母或数字组合。
return true;},
验证全部通过才返回 true
。
refresh()
表单重置
refresh(){this.student_id='';this.username='';this.password='',this.verify='',this.verify_number='',this.agreed=false,this.randomCode(); }
-
清空所有输入字段。
-
重新生成验证码。
-
注意:这里
this.password='',
末尾写成了逗号(,),在 JavaScript 中不是错误但不规范,建议统一用分号;
。
总结:核心逻辑概括
请求流程简述:
-
校验前端输入(judge 函数)
-
构建表单数据(student_id、username、password)
-
使用 Axios 发起异步请求
-
后端返回 JSON 响应(含 success 字段与 status 码)
-
根据不同状态码显示不同错误消息或跳转页面
功能 | 描述 |
---|---|
数据绑定 | 使用 data() 响应式变量 |
验证码 | 前端生成4位数+样式美化 |
表单验证 | 本地 JS 校验(格式、非空、一致性) |
注册请求 | 使用 axios POST 提交 x-www-form-urlencoded |
错误处理 | 支持后端错误与异常捕获 |
状态提示 | 使用 this.$message 弹出反馈 |
二、Register.vue
当然可以!下面我将逐行分析你这段 Vue 组件代码,帮助你全面理解这个用户注册组件的实现逻辑。该组件基于 Vue + Axios 实现,包含前端验证、验证码生成、注册请求等功能。
顶部结构
<script> export default {name: 'Login',
-
export default
:表示导出一个 Vue 组件对象。 -
name: 'Login'
:组件名为Login
,Vue DevTools 中会显示该名称。
data():定义组件状态数据
data() {return {student_id:'', // 学号username:'', // 用户名password:'', // 密码confirm_password:'', // 确认密码verify:'', // 用户输入的验证码verify_number:'', // 系统生成的验证码agreed:false, // 是否同意协议(勾选框)} },
-
data()
返回一个对象,里面是所有表单字段和校验相关变量。 -
Vue 会将这些字段“响应式绑定”到页面上。
mounted():生命周期钩子
mounted(){this.randomCode(); },
-
mounted
是 Vue 的生命周期函数,在组件挂载到页面后执行。 -
调用
randomCode()
:组件一加载就生成一个验证码。
methods:组件行为逻辑定义区
注册主逻辑
async register() {try {if(!this.judge()){this.refresh();return;}
-
调用
judge()
方法做前端验证,如果不合法就刷新并退出注册流程。
const formData = new URLSearchParams();formData.append('student_id', this.student_id);formData.append('username', this.username);formData.append('password', this.password);this.refresh();
-
创建
formData
并封装用户输入的注册信息,用于向服务器发送 POST 请求(使用 x-www-form-urlencoded 格式)。 -
成功之后立即调用
refresh()
,清空表单。
const response = await this.$axios.post('/api/userc?action=register', formData, {timeout: 5000});
-
使用
Axios
发送 POST 请求到/api/userc?action=register
接口。 -
设置了 5 秒超时限制。
if (response.data.success) {this.$message.success('注册成功');this.$router.push('/login');} else {this.$message.error(response.data.message || '注册失败');}
-
根据后端返回的数据判断注册是否成功:
-
成功:提示信息 + 跳转到登录页。
-
失败:显示后端提供的错误消息,或默认提示“注册失败”。
-
} catch (error) {this.$message.error('注册失败,请稍后重试');console.error('完整错误信息:', error);} }
-
捕获任何网络或服务器异常,防止程序崩溃,并给用户提示。
验证码生成器:randomCode()
randomCode() {this.verify_number = Math.floor(1000 + Math.random() * 9000).toString()
-
生成一个 1000–9999 之间的随机数字验证码,并转换为字符串。
let change = ((Math.ceil(Math.random() * 10)) + 100) % 4;let rgb1 = (Math.ceil(Math.random() * 1000) % 256);let rgb2 = (Math.ceil(Math.random() * 1000) % 256);let rgb3 = (Math.ceil(Math.random() * 1000) % 256);
-
随机生成一个背景颜色(rgb)和一个方向(0~3),用于验证码背景。
let v = document.querySelector('.verify_code');
-
获取页面中类名为
verify_code
的 DOM 元素(注意:这个用法不是 Vue 推荐方式)。
if(change==0)v.style.background=`linear-gradient(to bottom right,rgb(${rgb1},${rgb2},${rgb3}),black)`;else if(change==1)v.style.background=`linear-gradient(to top right,rgb(${rgb1},${rgb2},${rgb3}),black)`;...
-
设置不同方向的渐变背景样式,提高验证码识别难度,增强安全性。
judge():前端验证函数
if(!this.agreed){this.$message.error('请同意用户协议'); return false; }
-
检查是否勾选“同意协议”。
if(this.username=='' || this.password=='' || this.confirm_password=='' || this.verify=='' || this.student_id==''){this.$message.error('请输入完整信息');return false; }
-
检查输入项是否完整。
if(this.password != this.confirm_password){this.$message.error('两次密码输入不一致');return false; }
-
检查密码是否一致。
if(this.verify != this.verify_number){this.$message.error('验证码错误');this.randomCode(); return false; }
-
校验验证码是否正确,不通过就刷新验证码。
let student_id_reg = /^\d{9}$/; if(!student_id_reg.test(this.student_id)){this.$message.error('学号必须符合要求');return false; }
-
学号必须是9位数字。
let reg = /^[a-zA-Z0-9]{6,16}$/; if(!reg.test(this.password)){this.$message.error('密码格式错误');return false; }
-
密码必须是6~16位数字或字母。
return true;
-
所有验证通过,返回
true
。
refresh():重置表单内容
refresh(){this.student_id='';this.username='';this.password='',this.verify='',this.verify_number='',this.agreed=false,this.randomCode(); }
-
清空所有表单字段并重新生成验证码。
注意:逗号分隔变量赋值是有效但容易出错的写法,推荐写成多行形式。
总结:这个组件设计的优点
功能模块 | 描述 |
---|---|
表单数据处理 | 利用 data() 实现响应式数据双向绑定 |
生命周期使用 | mounted() 里生成验证码,合理触发初始化操作 |
用户验证 | 通过 judge() 实现前端校验,提高用户输入质量 |
交互反馈 | 使用 $message 显示提示信息 |
数据请求 | 通过 Axios 异步请求后端注册接口 |
安全性 | 包含验证码机制,简单防止机器注册 |
页面跳转 | 注册成功后跳转到 /login 页面 |
三、Home.vue
一、模块整体功能分析
这个模块是网站的“首页”或“主页”,其功能包括:
-
轮播图展示
-
通过
el-carousel
展示三张图片。
-
-
团队成员展示
-
使用卡片组件
el-card
列出团队成员。 -
点击卡片跳转到成员详情页。
-
-
公告列表展示
-
使用
el-table
列出公告的标题、创建者和时间。 -
鼠标悬停时间时显示完整时间(tooltip 提示)。
-
数据来源
该页面在 mounted
生命周期阶段,通过 Axios 向后端接口发起两次请求:
-
/api/announcementc?action=show
:获取公告列表。 -
/api/userc?action=major
:获取团队成员信息。
二、设计逻辑说明
1. 使用 Vue 生命周期:mounted()
-
为什么选择
mounted
而不是created
? 因为页面中涉及图片轮播、团队卡片、表格渲染等,需要依赖 DOM 渲染完成后进行展示,mounted
是更合适的时机。
2. Axios 异步请求
-
getAnnouncements()
和getmajor()
使用axios.get()
向服务端获取数据并绑定到组件的响应式变量announcements
和majors
。 -
使用
try-catch
异常捕获机制,增强健壮性。
三、详细讲解
import axios from 'axios';
-
导入 axios,用于发起 HTTP 请求。
import picture1 from '../../public/picture/picture1.jpg';
-
引入轮播图图片资源。
export default {name: 'Announcement',data() {return {announcements: [], // 公告数据pictures: [...], // 轮播图数据majors: [], // 团队成员数据}}, mounted() {this.getAnnouncements();this.getmajor(); }
-
生命周期钩子:组件加载完毕后立即发起数据请求。
methods: {goToMember(uid) {this.$router.push({path: '/userw',query: { uid: uid }});},
-
点击团队卡片跳转到
/userw?uid=...
页面。
shortTime(time){return time.split(' ')[0];},longTime(time){return time;},
-
用于公告时间显示处理,短时间只保留日期。
async getAnnouncements() {try {const response = await axios.get('/api/announcementc?action=show');this.announcements = response.data || [];} catch (err) {this.$message.error('获取公告失败,请稍后重试');}},
-
获取公告数据。
async getmajor(){try {const response = await axios.get('/api/userc?action=major');this.majors = response.data || [];} catch (err) {this.$message.error('获取成员失败,请稍后重试');}} }
-
获取成员信息数据。
总结:设计亮点
模块 | 设计点 | 目的 |
---|---|---|
轮播图 | 使用 el-carousel ,图片静态导入 | 页面视觉吸引力 |
团队成员 | v-for + 卡片点击跳转 | 支持查看个人详情 |
公告表格 | 支持 tooltip 查看时间详情 | 美观又实用 |
数据请求 | Axios + 生命周期 mounted | 页面加载自动拉取数据 |
样式 | 使用 scoped SCSS + Element Plus | 保持美观与模块化 |
四、Contest.vue
一、整体设计目的
基于 Vue + Element Plus 的比赛信息管理页面,结合了权限控制(admin
)、状态切换(编辑 / 添加)、数据双向绑定和远程请求处理(通过 $A.get
和 $A.getmessage
)。
二、数据结构与状态管理
data() {return {contests: [], // 比赛列表数组(从接口获取)isadding: false, // 当前是否处于添加比赛状态isediting: false, // 当前是否处于编辑比赛状态addDialogVisible: false, // 控制新增弹窗的显示admin: false, // 是否为管理员(从 sessionStorage 判断)editingcontest: { ... }, // 当前正在编辑的比赛数据对象newcontest: { ... } // 用于新增比赛的数据对象} }
状态变量的设计:
-
contests
是主列表内容。 -
isadding
控制是否在添加比赛,点击按钮切换。 -
isediting
只能编辑一场比赛,一旦点击切换状态。 -
admin
用于决定是否展示管理按钮(编辑、删除)。 -
editingcontest
是一个临时对象,保存当前被编辑的数据。 -
newcontest
也是临时对象,负责新增表单的内容。
三、生命周期钩子函数
created() {const user = JSON.parse(sessionStorage.getItem('user'));if(user){this.admin = user.admin || false;}this.getContests(); }
-
在
created()
生命周期中进行:-
从
sessionStorage
获取当前用户,判断其是否为管理员,控制权限显示。 -
调用
getContests()
方法获取比赛数据。
-
四、核心方法逐个分析
1. 获取比赛列表 getContests
getContests() {this.$A.get("contest&op=show", "other").then(res => this.contests = res); }
-
使用自定义封装的
this.$A.get
方法,向后端接口发请求,查询所有比赛数据。 -
结果保存到
contests
中进行渲染。
2. 显示新增弹窗 showAddDialog
showAddDialog() {this.addDialogVisible = true; }
-
控制新增比赛弹窗的显示状态。
3. 切换新增状态 addcontest
addcontest(){this.isadding = !this.isadding;if(!this.isadding){this.savecontest();} }
-
每次点击按钮切换
isadding
状态。 -
如果用户点击第二次(取消添加状态),就会自动调用
savecontest()
进行保存。
4. 保存新比赛 savecontest
savecontest() {const formData = new URLSearchParams();formData.append('title', this.newcontest.title);...this.$A.getmessage(formData, "contest&op=add", "other").then(() => {this.getContests(); // 更新页面数据this.newcontest = { title: '', level: '', organizer: '', type: '' }; // 清空表单}); }
-
收集
newcontest
表单数据,封装成formData
。 -
调用
$A.getmessage
向接口发送“添加比赛”请求。 -
成功后刷新比赛列表,并清空
newcontest
。
5. 编辑比赛 editcontest
editcontest(item) {if (this.isediting && this.editingcontest.cid === item.cid) {// 保存编辑内容...this.$A.getmessage(formData, "contest&op=update", "other").then(() => {this.isediting = false;this.getContests();});} else {// 开始编辑,复制对象this.editingcontest = {...item};this.isediting = true;} }
-
第一次点击:进入编辑模式,把目标
item
复制到editingcontest
。 -
第二次点击:如果再次点击相同比赛,表示“确认修改”,构建数据并发送更新请求。
-
请求成功后退出编辑状态并刷新数据。
6. 删除比赛 deletecontest
deletecontest(item) {this.$confirm('确定要删除此比赛吗?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {const formData = new URLSearchParams();formData.append('cid', item.cid);this.$A.getmessage(formData, "contest&op=delete", "other").then(() => this.getContests());}); }
-
弹出 Element Plus 的确认框。
-
用户确认后发送删除请求,请求成功后刷新列表。
五、组件与图标引用
import { Edit , Select, Plus , CloseBold} from '@element-plus/icons-vue'
-
从 Element Plus 引入图标组件,用于页面按钮视觉图标展示。
-
components: { Edit, Select, Plus, CloseBold }
注册后可在模板中使用这些图标。
六、总结:这个模块的设计意图
方面 | 说明 |
---|---|
交互逻辑 | 使用布尔状态 isadding 、isediting 控制表单状态,提高用户体验 |
权限控制 | 使用 admin 判断用户权限,控制功能是否可见(如增删改按钮) |
接口抽象 | 使用 this.$A.get / getmessage 代替原生 Axios,隐藏底层细节 |
数据双向绑定 | 所有表单数据通过 newcontest 和 editingcontest 绑定表单输入 |
接口统一 | 所有接口通过参数 contest&op=xxx 区分操作,符合 REST 风格 |
五、Nav.vue
第一部分:导入依赖
import "@/public/scss/index.scss"; import Newicon from "@/public/js/icon/index.js";
-
导入全局样式表(SCSS):使本组件拥有统一的样式外观;
-
引入图标数据或组件集合(如图标名称、SVG路径等)以供模板中使用。
export default
定义组件
export default {name: 'Nav',
-
定义组件名称为
Nav
,通常是顶部导航栏。
data()
- 组件状态变量定义
data() {return {Newicon: Newicon, // 引入的图标库(可供模板渲染使用)flag: false, // 表示是否登录(true 为已登录)username: '', // 当前用户名is_drop_down: false // 控制用户头像的下拉框显示状态} },
watch
- 监听路由变化
watch: {'$route'() {this.checkLoginStatus()}, },
-
监听路由变化,当页面跳转时重新检查登录状态;
-
避免用户跳转页面后
flag/username
状态未更新。
生命周期钩子
mounted() {this.checkLoginStatus();window.addEventListener('storage', this.checkLoginStatus); }, beforeDestroy() {window.removeEventListener('storage', this.checkLoginStatus); },
-
mounted
:初始化页面时立即检查 session 中的用户信息; -
注册
storage
事件监听器,以检测跨标签页的登录状态变化(例如:一个标签页登出后,另一个也能感知); -
beforeDestroy
用于解绑监听器(但beforeDestroy
是 Vue 2 的钩子名,若是 Vue 3,应使用beforeUnmount
)。
methods
- 组件方法定义
1. 获取 CSS 变量
getCssVariable(name) {return getComputedStyle(document.documentElement).getPropertyValue(name); },
获取 CSS 自定义属性值(如
--special-color
),用于动态样式变换。
2. 鼠标悬浮变色
mousein(e) {const specialColor = this.getCssVariable('--special-color');e.target.style.color = `${specialColor}`; }, mouseout(e) {const normalColor = this.getCssVariable('--normal-color');e.target.style.color = `${normalColor}`; },
悬浮时使用
--special-color
,移出时恢复为--normal-color
; 实现视觉反馈效果,增强用户体验。
3. 控制下拉菜单显示
dropdown_open() {this.is_drop_down = true; }, dropdown_close() {this.is_drop_down = false; },
控制下拉状态(如点击头像后显示“退出登录”等选项)。
4. 登录状态检查
checkLoginStatus() {try {const user = JSON.parse(sessionStorage.getItem('user'));this.flag = true;this.username = user.username;} catch {this.flag = false;this.username = '';} },
从
sessionStorage
中读取用户对象(假设登录时已经存入); 读取成功则设置flag=true
和用户名,否则视为未登录。
5. 登出操作
logout() {sessionStorage.removeItem('user'); }
删除本地 session 中用户信息,实现“登出”操作; 建议添加:刷新页面或跳转登录页的逻辑,否则前端状态不会立即响应变化。
总结:该脚本实现功能如下:
功能项 | 描述 |
---|---|
登录状态管理 | 读取 sessionStorage 中用户信息,确定是否已登录 |
用户名显示 | 登录后显示用户名,登出后清空 |
下拉菜单控制 | 用户头像点击时展开/收起下拉菜单 |
鼠标悬浮样式控制 | 利用 CSS 变量控制文字颜色动态变换 |
登录状态同步 | 使用 storage 事件监听器实现多标签页间同步 |
动态图标支持 | 引入图标集合 Newicon 可用于 UI 图标化 |