负责模块解析-赵家康

一、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 图标化 |