在之前的十几篇文章中,整个BuildAdmin后台管理系统完成了layout布局、菜单栏、tabs标签栏的设计,那么后端管理系统整体框架的最后一个部分就是导航菜单栏。
导航菜单栏不多,就是一些非必要功能的集合,但是比较有意思,所以花点时间实现这部分功能。
导航菜单栏和tab栏都在layout布局的的header部分。tab栏在左侧,导航菜单栏在右侧,在BuilderAdmin中,一个设计了7个功能模块。
7个按钮分别对应的是:回到首页、中英文切换、浏览器全屏、运行终端命令、清除缓存、个人信息、系统设置。这里先实现整个菜单栏框架,然后再逐一实现功能。
先定义一个navMenus.vue,渲染导航菜单栏的各个按钮。
这里只是单纯的定义了按钮,没有添加样式,先看看效果。
添加css样之后,整体布局如下。
图标部分后面会微调,整个菜单栏前端代码如下:
<div class="nav-menus">
<div class="nav-menu-item">
<Icon class="nav-menu-icon" :color="config.getColorVal('headerBarTabColor')" name="el-icon-Monitor"size="18"/>
</div>
<div class="nav-menu-item">
<Icon class="nav-menu-icon" :color="config.getColorVal('headerBarTabColor')" name="local-lang" size="18"/>
</div>
<div class="nav-menu-item">
<Icon class="nav-menu-icon" :color="config.getColorVal('headerBarTabColor')" name="el-icon-FullScreen" size="18"/>
</div>
<div class="nav-menu-item">
<Icon class="nav-menu-icon" :color="config.getColorVal('headerBarTabColor')" name="local-terminal" size="26"/>
</div>
<div class="nav-menu-item">
<Icon class="nav-menu-icon" :color="config.getColorVal('headerBarTabColor')" name="el-icon-Delete" size="18"/>
</div>
<div class="nav-menu-item">
<img src="@/assets/logo.png" style="height: 20px; width: 20px" alt=""/>
admin
<div>
<div class="nav-menu-item">
<Icon class="nav-menu-icon" :color="config.getColorVal('headerBarTabColor')" name="fa fa-cogs" size="18"/>
</div>
</div>
这个模块还是比较简单的,在BuildAdmin中这个回到首页的功能是:打开一个新的标签页,回到BuildAdmin的官网首页。实现原理就是点击一下,跳转到BuildAdmin的首页,也就是一个\<a>标签。在vue的架构中,使用router来实现跳转。
我在这里的设计是回到/首页,也就是dashboard。但是我有担心误点击导致数据丢失,所以保持当前标签页不变动,在新标签页回到首页。
<router-link class="h100" target="_blank" title="首页" to="/">
<!-- 回到首页的组件 -->
</router-link>
如图:
中英文切换使用的是vue-i18n实现的,例如t('Home'),英文模式下显示“Home"在中文模式下就变成了”首页”。
中英文切换的设计,对于我来说没有什么太大作用,于是我就给去掉了,打算在菜单栏后面补充一个暗黑风格切换按钮,因为设计布局的问题,这个留着后面写。
在之前的tabs实现的时候,写过一个全屏。不过那个是main区域页面的全屏,是通过隐藏aside菜单边栏和tabs导航栏实现的,如图:
而这里说的全屏,指的是浏览器实现全屏,如图所示:
在点击全屏之后,除了页面全屏之外,全屏图标也是发生了变化,同时页面上方提示“按ESC即可退出全屏模式”。实现全屏这一功能使用的是screenfull库,执行下面命令进行安装。
npm install screenfull
因为之前tab功能的页面全屏涉及了多个组件(header、aside),各个组件之间需要通信,来完成隐藏展开,所以在使用pinia定义了全局共享变量navTabs.state.tabFullScreen,具体实现可以参考之前的文章:BuildAdmin16:边栏隐藏、页面全屏,我用vue是如何实现的
在上面全屏的组件上添加需要的功能:
<div @click="onFullScreen" class="nav-menu-item" :class="state.isFullScreen ? 'hover' : ''">
<Icon
:color="configStore.getColorVal('headerBarTabColor')"
class="nav-menu-icon"
v-if="state.isFullScreen"
name="local-full-screen-cancel"
size="18"
/>
<Icon :color="configStore.getColorVal('headerBarTabColor')" class="nav-menu-icon" v-else name="el-icon-FullScreen" size="18" />
这里给全屏图标添加click点击事件onFullScreen,并定义两个图标,一个是全屏图标,一个是取消全屏图标,通过v-if/v-else来判断哪个图标被展示,如果图标切换频繁的话,这里使用v-show更为合适。
通过共享变量state.isFullScreen来作为是否全屏的判断条件。这里通过isFullScreen来实现全屏/取消全屏状态判断,以及图标的切换。
import {reactive} from "vue";
import screenfull from "screenfull";
import {ElMessage} from "element-plus";
const ref = reactive({
isFullScreen: true
})
const onFullScreen = () => {
if (!screenfull.isEnabled) {
ElMessage({
showClose: false,
message: 'layouts.Full screen is not supported.',
type: 'warning',
})
return false
}
screenfull.toggle()
screenfull.onchange(() => {
state.isFullScreen = screenfull.isFullscreen
})
}
toggle方法会请求全屏,如果当前是全屏则会退出全屏,onchange是全屏/取消全屏触发时的回调函数,isFullscreen表示当前是否为全屏,此变量用来修改state的isFullScreen。看一下全屏功能演示:
css部分分为基本的布局、样式和动画,先实现基本的css。
.nav-menus {
border-radius: var(--el-border-radius-base);
box-shadow: var(--el-box-shadow-light);
display: flex;
align-items: center;
height: 100%;
margin-left: auto;
background-color: v-bind('config.getColorVal("headerBarBackground")');
overflow: hidden;
}
.nav-menu-item {
height: 100%;
width: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
除了基本的背景色设置,整个菜单栏使用的是flex弹性布局、水平、横向居中。动画部分就是鼠标悬停在图标的时候,会触发一个缩小再变大的动画。
从设计上来看,就是先缩小、再放大、最后恢复正常三个部分,使用scale即可以实现。
nav-menu-item:hover {
.icon {
animation: twinkle 0.3s ease-in-out;
}
}
@keyframes twinkle {
0% {
transform: scale(0);
}
80% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
使用 @keyframes 定义一个动画,当鼠标悬停图标的时候,触发动画。
本篇文章除了讲了菜单栏的布局之外,大部分篇幅讲了浏览器全屏的实现,主要是使用scrrenfull库,代码很简单,主要是要借鉴思路。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。