页面顶部导航栏(Navbar)的功能(Navbar/index.vue)
这段代码是一个 Vue.js 组件,实现了页面顶部导航栏(Navbar)的功能。我将分块分析它的各个部分:
模板 (Template):
<!-- spid-admin/src/layout/components/Navbar/index.vue -->
<template><div class="navbar"><hamburgerid="hamburger-container":is-active="sidebar.opened"class="hamburger-container"@toggleClick="toggleSideBar"/><breadcrumbid="breadcrumb-container"class="breadcrumb-container"/><!-- <lang-select /> --><div class="right-menu"><template v-if="device!=='mobile'"><div style="position: relative; display: inline-block; padding: 0 8px; height: 100%; color: #5a5e66; vertical-align: text-bottom; cursor: pointer;" @click="handleToNotice"><el-image :src="noticePic" style="width: 35px; height: 35px; position: relative; top: 7px;" /></div><div v-if="isVip" style="position: relative; display: inline-block; padding: 0 4px; height: 100%; color: #5a5e66; vertical-align: text-bottom; cursor: pointer;" @click="handleToMission"><el-image :src="systemTaskPic" style="width: 35px; height: 35px; position: relative; top: 7px;" /></div><!-- <header-search class="right-menu-item" /> --><!-- <error-log class="errLog-container right-menu-item hover-effect" /> --><screenfull class="right-menu-item hover-effect" /><!-- <el-tooltip:content="$t('navbar.size')"effect="dark"placement="bottom"><size-select class="right-menu-item hover-effect" /></el-tooltip> --><!-- <lang-select class="right-menu-item hover-effect" /> --><span class="username">{{ username }}</span></template><el-dropdownclass="avatar-container right-menu-item hover-effect"trigger="click"><div class="avatar-wrapper"><imgv-if="avatar":src="oss + avatar"class="user-avatar"><imgv-else:src="require('@/assets/images/logo.jpg')"class="user-avatar"><i class="el-icon-caret-bottom" /></div><el-dropdown-menu slot="dropdown"><router-link to="/"><el-dropdown-item>{{ $t('navbar.dashboard') }}</el-dropdown-item></router-link><router-link to="/setting/profile/"><el-dropdown-item>{{ $t('navbar.profile') }}</el-dropdown-item></router-link><router-link to="/subscribe/list/"><el-dropdown-item>订阅续期</el-dropdown-item></router-link><router-link to="/account/child/"><el-dropdown-item>账号分身</el-dropdown-item></router-link><el-dropdown-itemdivided@click.native="logout"><span style="display:block;">{{ $t('navbar.logOut') }}</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div></div>
</template>
navbar: 导航栏的容器。hamburger: 汉堡按钮,用于切换侧边栏的显示和隐藏,@toggleClick="toggleSideBar"点击事件触发toggleSideBar方法。breadcrumb: 面包屑导航。right-menu: 右侧菜单区域。v-if="device!=='mobile'": 判断当前设备是否为移动设备,如果是,则不显示下列内容。- 通知图标: 使用
el-image显示通知图标,@click="handleToNotice"点击事件触发handleToNotice方法,跳转到通知列表。
- 通知图标: 使用
- 任务图标: 使用
el-image显示任务图标,v-if="isVip"判断用户是否是vip,如果是vip则显示任务图标。@click="handleToMission"点击事件触发handleToMission方法,跳转到任务列表。
*screenfull: 全屏切换按钮。
*username: 显示用户名。 el-dropdown: 下拉菜单,用于显示用户头像和一些操作选项。avatar-wrapper: 头像容器。v-if="avatar": 判断用户是否有头像, 如果有头像,则拼接oss和avatar作为头像的url, 否则使用默认的logo作为头像el-dropdown-menu: 下拉菜单项。router-link: 使用router-link组件创建路由链接。el-dropdown-item: 下拉菜单项。@click.native="logout": 点击退出登录按钮,触发logout方法。
脚本 (Script):
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import { AppModule } from '@/store/modules/app'
import { UserModule } from '@/store/modules/user'
import Breadcrumb from '@/components/Breadcrumb/index.vue'
import ErrorLog from '@/components/ErrorLog/index.vue'
import Hamburger from '@/components/Hamburger/index.vue'
import HeaderSearch from '@/components/HeaderSearch/index.vue'
import LangSelect from '@/components/LangSelect/index.vue'
import Screenfull from '@/components/Screenfull/index.vue'
import SizeSelect from '@/components/SizeSelect/index.vue'@Component({name: 'Navbar',components: {Breadcrumb,ErrorLog,Hamburger,HeaderSearch,LangSelect,Screenfull,SizeSelect}
})
export default class extends Vue {get sidebar() {return AppModule.sidebar}get device() {return AppModule.device.toString()}get avatar() {return UserModule.avatar}get username() {return UserModule.username}get oss() {return AppModule.oss}get noticeNum() {// console.log('改变触发')// console.log(AppModule.notices)return AppModule.notices}@Watch('noticeNum')watchV(v: any) {this.setData()}public role = UserModule.roles[0]public isVip: boolean = JSON.parse(UserModule.token).vippublic noticePic = require(`@/assets/images/notice-0.png`)public systemTaskPic = require(`@/assets/images/system-task.png`)private toggleSideBar() {AppModule.ToggleSideBar(false)}private async logout() {await UserModule.LogOut()this.$router.push(`/login?redirect=${this.$route.fullPath}`)}private handleToNotice() {this.$router.push(`/notice/list`)}private handleToMission() {if (this.role === 'ROLE_SUPER') {this.$router.push(`/mission/super-list`)} else {this.$router.push(`/mission/company-list`)}}private async setData() {const num = parseInt(this.noticeNum)this.noticePic = require(`@/assets/images/notice-${!num ? '0' : num > 9 ? 'n' : num}.png`)}created() {this.setData()}
}
</script>
- 引入依赖: 引入
vue-property-decorator,AppModule,UserModule, 以及各种组件。 - 组件定义: 使用
@Component装饰器定义组件,名称为Navbar。 - 计算属性:
sidebar: 获取AppModule中的侧边栏状态。device: 获取AppModule中的设备类型。avatar: 获取UserModule中的用户头像。username: 获取UserModule中的用户名。oss: 获取AppModule中的 OSS 地址前缀。noticeNum: 获取AppModule中的通知数量。
@Watch('noticeNum'): 监听noticeNum的变化,如果发生变化,则调用setData方法。- 数据属性:
role: 获取UserModule中的用户角色。isVip: 获取UserModule中的用户是否是 VIP。noticePic: 通知图标的路径。systemTaskPic: 任务图标的路径。
- 方法:
toggleSideBar(): 调用AppModule.ToggleSideBar()方法切换侧边栏的显示和隐藏。logout(): 调用UserModule.LogOut()方法退出登录,并跳转到登录页。handleToNotice(): 跳转到通知列表页。handleToMission(): 根据用户角色跳转到对应的任务列表页。setData(): 根据通知数量设置noticePic的路径。
- 生命周期钩子:
created(): 调用setData()方法,初始化通知图标。
样式 (Style):
<style lang="scss" scoped>
.navbar {// ... 导航栏样式
}
</style>
navbar: 导航栏容器的样式,设置高度、背景颜色、阴影等。hamburger-container: 汉堡按钮容器的样式,设置高度、浮动、内边距、光标等。breadcrumb-container: 面包屑导航容器的样式,设置浮动。errLog-container: 错误日志容器的样式,设置display: inline-block和vertical-align: top。right-menu: 右侧菜单容器的样式,设置浮动、高度、行高。right-menu-item: 右侧菜单项的样式,设置display: inline-block、内边距、高度、字体大小、颜色等。hover-effect: 鼠标悬停效果,设置光标和过渡效果。avatar-container: 头像容器的样式,设置外边距。avatar-wrapper: 头像包装器的样式,设置外边距和相对定位。user-avatar: 用户头像的样式,设置光标、宽度、高度、圆角。el-icon-caret-bottom: 下拉图标的样式,设置光标、绝对定位、字体大小。username: 用户名的样式,设置display: inline-block、vertical-align: text-bottom、内边距、颜色、字体大小和鼠标悬停效果。
总结:
这段代码实现了一个功能完备的页面顶部导航栏,包括:
- 汉堡按钮
- 面包屑导航
- 通知图标
- 系统任务图标 (VIP用户专属)
- 全屏切换按钮
- 用户名显示
- 用户头像下拉菜单(包含常用操作和退出登录)
代码结构清晰,使用了 Vuex 管理状态,并使用了 vue-property-decorator 简化组件编写。
可以改进的地方:
- 组件拆分: 可以将右侧菜单区域拆分成更小的组件,例如将通知图标、任务图标、用户名和头像下拉菜单拆分成独立的组件,提高代码的可复用性和可维护性。
- 国际化: 可以将硬编码的中文文本替换成国际化资源,例如“订阅续期”、“账号分身”等。
- 错误处理: 可以添加更详细的错误处理,例如在
logout方法中捕获错误并提示用户。 - 代码注释: 可以添加更详细的代码注释,方便其他开发人员理解代码的逻辑。
<!-- spid-admin/src/layout/components/Navbar/index.vue -->
<template><div class="navbar"><hamburgerid="hamburger-container":is-active="sidebar.opened"class="hamburger-container"@toggleClick="toggleSideBar"/><breadcrumbid="breadcrumb-container"class="breadcrumb-container"/><!-- <lang-select /> --><div class="right-menu"><template v-if="device!=='mobile'"><div style="position: relative; display: inline-block; padding: 0 8px; height: 100%; color: #5a5e66; vertical-align: text-bottom; cursor: pointer;" @click="handleToNotice"><el-image :src="noticePic" style="width: 35px; height: 35px; position: relative; top: 7px;" /></div><div v-if="isVip" style="position: relative; display: inline-block; padding: 0 4px; height: 100%; color: #5a5e66; vertical-align: text-bottom; cursor: pointer;" @click="handleToMission"><el-image :src="systemTaskPic" style="width: 35px; height: 35px; position: relative; top: 7px;" /></div><!-- <header-search class="right-menu-item" /> --><!-- <error-log class="errLog-container right-menu-item hover-effect" /> --><screenfull class="right-menu-item hover-effect" /><!-- <el-tooltip:content="$t('navbar.size')"effect="dark"placement="bottom"><size-select class="right-menu-item hover-effect" /></el-tooltip> --><!-- <lang-select class="right-menu-item hover-effect" /> --><span class="username">{{ username }}</span></template><el-dropdownclass="avatar-container right-menu-item hover-effect"trigger="click"><div class="avatar-wrapper"><imgv-if="avatar":src="oss + avatar"class="user-avatar"><imgv-else:src="require('@/assets/images/logo.jpg')"class="user-avatar"><i class="el-icon-caret-bottom" /></div><el-dropdown-menu slot="dropdown"><router-link to="/"><el-dropdown-item>{{ $t('navbar.dashboard') }}</el-dropdown-item></router-link><router-link to="/setting/profile/"><el-dropdown-item>{{ $t('navbar.profile') }}</el-dropdown-item></router-link><router-link to="/subscribe/list/"><el-dropdown-item>订阅续期</el-dropdown-item></router-link><router-link to="/account/child/"><el-dropdown-item>账号分身</el-dropdown-item></router-link><el-dropdown-itemdivided@click.native="logout"><span style="display:block;">{{ $t('navbar.logOut') }}</span></el-dropdown-item></el-dropdown-menu></el-dropdown></div></div>
</template><script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator'
import { AppModule } from '@/store/modules/app'
import { UserModule } from '@/store/modules/user'
import Breadcrumb from '@/components/Breadcrumb/index.vue'
import ErrorLog from '@/components/ErrorLog/index.vue'
import Hamburger from '@/components/Hamburger/index.vue'
import HeaderSearch from '@/components/HeaderSearch/index.vue'
import LangSelect from '@/components/LangSelect/index.vue'
import Screenfull from '@/components/Screenfull/index.vue'
import SizeSelect from '@/components/SizeSelect/index.vue'@Component({name: 'Navbar',components: {Breadcrumb,ErrorLog,Hamburger,HeaderSearch,LangSelect,Screenfull,SizeSelect}
})
export default class extends Vue {get sidebar() {return AppModule.sidebar}get device() {return AppModule.device.toString()}get avatar() {return UserModule.avatar}get username() {return UserModule.username}get oss() {return AppModule.oss}get noticeNum() {// console.log('改变触发')// console.log(AppModule.notices)return AppModule.notices}@Watch('noticeNum')watchV(v: any) {this.setData()}public role = UserModule.roles[0]public isVip: boolean = JSON.parse(UserModule.token).vippublic noticePic = require(`@/assets/images/notice-0.png`)public systemTaskPic = require(`@/assets/images/system-task.png`)private toggleSideBar() {AppModule.ToggleSideBar(false)}private async logout() {await UserModule.LogOut()this.$router.push(`/login?redirect=${this.$route.fullPath}`)}private handleToNotice() {this.$router.push(`/notice/list`)}private handleToMission() {if (this.role === 'ROLE_SUPER') {this.$router.push(`/mission/super-list`)} else {this.$router.push(`/mission/company-list`)}}private async setData() {const num = parseInt(this.noticeNum)this.noticePic = require(`@/assets/images/notice-${!num ? '0' : num > 9 ? 'n' : num}.png`)}created() {this.setData()}
}
</script><style lang="scss" scoped>
.navbar {height: 50px;overflow: hidden;position: relative;background: #fff;box-shadow: 0 1px 4px rgba(0,21,41,.08);.hamburger-container {line-height: 46px;height: 100%;float: left;padding: 0 15px;cursor: pointer;transition: background .3s;-webkit-tap-highlight-color:transparent;&:hover {background: rgba(0, 0, 0, .025)}}.breadcrumb-container {float: left;}.errLog-container {display: inline-block;vertical-align: top;}.right-menu {float: right;height: 100%;line-height: 50px;&:focus {outline: none;}.right-menu-item {display: inline-block;padding: 0 8px;height: 100%;font-size: 22px;color: #5a5e66;vertical-align: text-bottom;&.hover-effect {cursor: pointer;transition: background .3s;&:hover {background: rgba(0, 0, 0, .025)}}}.avatar-container {margin-right: 30px;.avatar-wrapper {margin-top: 5px;position: relative;.user-avatar {cursor: pointer;width: 40px;height: 40px;border-radius: 10px;}.el-icon-caret-bottom {cursor: pointer;position: absolute;right: -20px;top: 25px;font-size: 12px;}}}}.username {display: inline-block;vertical-align: text-bottom;padding: 0 8px;color: #1890ff;font-size: 12px;&:hover {color: #46a6ff;}}
}
</style>

相关文章:
页面顶部导航栏(Navbar)的功能(Navbar/index.vue)
这段代码是一个 Vue.js 组件,实现了页面顶部导航栏(Navbar)的功能。我将分块分析它的各个部分: 模板 (Template): <!-- spid-admin/src/layout/components/Navbar/index.vue --> <template><div class"navb…...
thinnkphp5.1和 thinkphp6以及nginx,apache 解决跨域问题
ThinkPHP 5.1 使用中间件设置响应头 ThinkPHP 5.1 及以上版本支持中间件,可以通过中间件统一设置跨域响应头。 步骤: 创建一个中间件文件,例如 CorsMiddleware.php: namespace app\middleware;class CorsMiddleware {public fu…...
vue2新增删除
(只是页面实现,不涉及数据库) list组件: <button click"onAdd">新增</button><el-table:header-cell-style"{ textAlign: center }" :cell-style"{ textAlign: center }":data&quo…...
测试ip端口-telnet开启与使用
前言 开发过程中我们总会要去测试ip通不通,或者ip下某个端口是否可以联通,为此我们可以使用telnet 命令来实现。 一、telnet 开启 可能有些人使用telnet报错,不是内部命令,可以如下开启: 1、打开控制面板ÿ…...
Python爬虫基础——XPath表达式
首先说一下这节内容在学习过程中存在的问题吧,在爬取百度网页文字时,出现了问题,就是通过表达式在网页搜索中可以定位,但是通过代码无法定位,请教了一位老师,他说是动态链接,目前这部分内容比较…...
ansible-性能优化
一. 简述: 搞过运维自动化工具的人,肯定会发现很多运维伙伴们经常用saltstack和ansible做比较,单从执行效率上来说,ansible确实比不上saltstack(ansible使用的是ssh,salt使用的是zeromq消息队列[暂没深入了解]),但其实…...
高等数学学习笔记 ☞ 一元函数微分的基础知识
1. 微分的定义 (1)定义:设函数在点的某领域内有定义,取附近的点,对应的函数值分别为和, 令,若可以表示成,则称函数在点是可微的。 【 若函数在点是可微的,则可以表达为】…...
前后端实现防抖节流实现
在前端和 Java 后端中实现防抖(Debounce)和节流(Throttle)主要用于减少频繁请求或事件触发对系统的压力。前端和后端的实现方式有些不同,以下是两种方法的具体实现: 1. 前端实现防抖和节流 在前端中&…...
【笔记】算法记录
1、求一个数的素因子(试除法) // 获取一个数的所有素因子 set<int> getPrimeFactors(int num) {set<int> primeFactors;for (int i 2; i * i < num; i) {while (num % i 0) {primeFactors.insert(i);num / i;}}if (num > 1) {prime…...
【网络云SRE运维开发】2025第2周-每日【2025/01/08】小测-【第8章 STP生成树协议】理论和实操解析
文章目录 一、选择题二、理论题三、实操题 【网络云SRE运维开发】2025第2周-每日【2025/01/08】小测-【第8章 STP生成树协议】理论和实操解析 一、选择题 生成树协议的主要作用是 B. 防止网络环路解释:生成树协议(STP)的主要目的是防止网络中…...
git push -f 指定分支
要将本地代码推送到指定的远程分支,你可以使用以下步骤和命令: 确认远程仓库: 确保你的本地仓库已经与远程仓库关联。你可以使用以下命令查看当前的远程仓库状态: git remote -v查看本地分支: 使用命令查看当前存在的本…...
CTF知识点总结(二)
异或注入:两个条件相同(同真或同假)即为假。 http://120.24.86.145:9004/1ndex.php?id1^(length(union)!0)-- 如上,如果union被过滤,则 length(union)!0 为假,那么返回页面正常。 2|0updatexml() 函数报…...
解决Edge打开PDF总是没有焦点
【问题描述】 使用Edge浏览器作为默认PDF阅读器打开本地PDF文件,Edge窗口总是不获得焦点,而是在任务栏以橙色显示,需要再手动点击一次才能查看文件内容。 本强迫症来治一治这个问题! 【解决方法】 GPT老师指出问题出在Edge的启动…...
69.基于SpringBoot + Vue实现的前后端分离-家乡特色推荐系统(项目 + 论文PPT)
项目介绍 在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括家乡特色推荐的网络应用,在外国家乡特色推荐系统已经是很普遍的方式,不过国内的管理网站可能还处于起步阶段。家乡特色推荐系统采用java技术&…...
计算机视觉目标检测-DETR网络
目录 摘要abstractDETR目标检测网络详解二分图匹配和损失函数 DETR总结总结 摘要 DETR(DEtection TRansformer)是由Facebook AI提出的一种基于Transformer架构的端到端目标检测方法。它通过将目标检测建模为集合预测问题,摒弃了锚框设计和非…...
《自动驾驶与机器人中的SLAM技术》ch1:自动驾驶
目录 1.1 自动驾驶技术 1.2 自动驾驶中的定位与地图 1.1 自动驾驶技术 1.2 自动驾驶中的定位与地图 L2 在技术实现上会更倾向于实时感知,乃至可以使用感知结果直接构建鸟瞰图(bird eye view, BEV),而 L4 则依赖离线地图。 高精地…...
【UE5 C++课程系列笔记】23——多线程基础——AsyncTask
目录 概念 函数说明 注意事项 (1)线程安全问题 (2)依赖特定线程执行的任务限制 (3)任务执行顺序和时间不确定性 使用示例 概念 AsyncTask 允许开发者将一个函数或者一段代码逻辑提交到特定的线程去执…...
基于Python的音乐播放器 毕业设计-附源码73733
摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器,用户可以轻松管理自己的音乐库,播放喜爱的音乐,并享受音乐带来的愉悦体验。 首先,我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…...
cursor vip
https://cursor.jeter.eu.org?pf7f4f3fab0af4119bece19ff4a4360c3 可以直接复制命令使用git bash执行即可 命令: bash <(curl -Lk https://gitee.com/kingparks/cursor-vip/releases/download/latest/ic.sh) f7f4f3fab0af4119bece19ff4a4360c3 等待执行完成后…...
Docker部署项目,Mysql数据库总是宕机并且上传数据全部被删除了
刚开始排查原因我以为是一些内存占用问题的原因,后来查看数据库日志发现有多个异常ip尝试连接数据库并且也连接成功了随后数据库就被异常关闭了,然后我就重启容器远程连接数据库发现数据全没了,又在数据库中找到了如下内容: All y…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
Android15默认授权浮窗权限
我们经常有那种需求,客户需要定制的apk集成在ROM中,并且默认授予其【显示在其他应用的上层】权限,也就是我们常说的浮窗权限,那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
