vue自定义大小导航展开收缩的效果
vue自定义大小导航展开收缩的效果pc端业务开发中,我们经常会遇到左右布局的页面(左为navigation bar, 右为content),为了适应笔记本小屏的情况,常把左侧的导航栏做成可以收缩的状态,使页面的布局更加的合理,贴近用户的使用。HTML<div class="my-slider" :class="{ 'my-slider-width': !navShow, 'my-ho...
·
vue自定义大小导航展开收缩的效果
pc端业务开发中,我们经常会遇到左右布局的页面(左为navigation bar, 右为content),为了适应笔记本小屏的情况,常把左侧的导航栏做成可以收缩的状态,使页面的布局更加的合理,贴近用户的使用。
HTML
<div class="my-slider" :class="{ 'my-slider-width': !navShow, 'my-hover-width': hoverShow }">
<!-- LOGO -->
<div class="my-slider-icon-logo">
<i class="icon icon-logo"></i>
<span class="my-slider-content" :class="{ 'my-slider-none': (!navShow && !hoverShow) }">我的个人中心</span>
</div>
<!-- icon开关 -->
<div class="my-slider-back"
:class="{ 'my-slider-width': !navShow }"
@click="showNavIcon">
<i class="icon icon-dedent" v-if="navShow"></i>
<i class="icon icon-indent" v-else></i>
</div>
<!-- content -->
<div class="my-nav"
@mouseover="hoverInfo"
@mouseout="hoverInfo">
<ul class="my-navbar">
<li
v-for="(item, index) in menuInfo"
:key="index"
v-if="item.show"
class="my-nav-child"
:class="{
'my-nav-click': $route.path === item.pathName,
'my-nav-show': item.itemsShow }">
<template v-if="item.pathName !== 'line'">
<a class="my-nav-a"
href="javascript:;"
v-if="item.pathName"
@click="routerTo(item)">
<i class="my-icon my-icon-color"
:class="[item.iconName]"></i>
<span class="my-nav-span">{{item.name}}</span>
</a>
<a class="my-nav-a"
href="javascript:;"
v-else
@click="openShow(item, index)">
<i class="my-icon my-icon-color" :class="[item.iconName]"></i>
<span class="my-nav-span">{{item.name}}</span>
<template v-if="navShow || hoverShow">
<i class="my-icon icon-angle-down"
style="font-weight: bold;"
v-if="!item.itemsShow && !item.pathName"></i>
<i class="my-icon icon-angle-up"
style="font-weight: bold;"
v-if="item.itemsShow && !item.pathName"></i>
</template>
</a>
</template>
<template v-else>
<a href="javascript:;" class="my-nav-a my-line-a">
<span v-if="navShow || hoverShow">切割线</span>
<span class="my-left-line"></span>
<span class="my-right-line" v-if="navShow || hoverShow"></span>
</a>
</template>
<collapse-transition>
<template v-if="!item.pathName">
<div class="my-box-info" v-if="item.itemsShow">
<li
:class="{ 'my-nav-click': $route.path === node.pathName }"
v-for="(node, nodeIndex) in item.items"
:key="nodeIndex"
v-if="node.show">
<a class="my-nav-a"
href="javascript:;"
@click="routerTo(node)">
<span class="my-point"></span>
<span class="my-nav-span">{{node.name}}</span>
</a>
</li>
</div>
</template>
</collapse-transition>
</li>
</ul>
</div>
</div>
methods
import collapseTransition from './collapse-transition'
export default {
components: { collapseTransition },
data () {
return {
navShow: true,
hoverShow: false,
// 导航数据
menuInfo: [
{
name: '个人资料',
pathName: '/',
roleId: 'data',
iconName: 'icon-work-info',
items: [],
show: true,
itemsShow: false
},
{
name: '我的收藏',
pathName: '/collection',
roleId: 'collection',
iconName: 'icon-work-info',
items: [],
show: true,
itemsShow: false
},
{
name: '我的爱好',
pathName: '',
roleId: 'role',
iconName: 'icon-work-info',
items: [
{
name: '写代码',
pathName: '/write',
roleId: 'serviceEntry',
show: true
},
{
name: '改BUG',
pathName: '/change',
roleId: 'directory',
show: true
}
],
show: true,
itemsShow: false
},
{
name: '我的关注',
pathName: '/focus',
roleId: 'focus',
iconName: 'icon-work-info',
items: [],
show: true,
itemsShow: false
},
{
name: '切割线',
pathName: 'line',
roleId: 'line',
iconName: '',
items: [],
show: true,
itemsShow: false
},
{
name: '我的下载',
pathName: '',
roleId: 'role',
iconName: 'icon-work-info',
items: [
{
name: '知识下载',
pathName: '/knowledge',
roleId: 'knowledge',
show: true
},
{
name: '目录下载',
pathName: '/directory',
roleId: 'directory',
show: true
}
],
show: true,
itemsShow: false
},
{
name: '我的游戏',
pathName: '',
roleId: 'role',
iconName: 'icon-work-info',
items: [
{
name: 'QQ农场',
pathName: '/farm',
roleId: 'change',
show: true
},
{
name: 'QQ斗地主',
pathName: '/landlord',
roleId: 'landlord',
show: true
},
{
name: 'QQ飞车',
pathName: '/coaster',
roleId: 'coaster',
show: true
}
],
show: true,
itemsShow: false
},
{
name: '我的学院',
pathName: '/college',
roleId: 'college',
iconName: 'icon-work-info',
items: [],
show: true,
itemsShow: false
},
{
name: '我的资料',
pathName: '',
roleId: 'role',
iconName: 'icon-work-info',
items: [
{
name: 'vue',
pathName: '/vue',
roleId: 'vue',
show: true
},
{
name: 'react',
pathName: '/react',
roleId: 'react',
show: true
},
{
name: 'node',
pathName: '/node',
roleId: 'node',
show: true
}
],
show: true,
itemsShow: false
}
]
}
},
methods: {
// 展开子集列
openShow (item, index) {
if (item.pathName) {
return
}
for (let i = 0; i < this.menuInfo.length; i++) {
if (this.menuInfo[i].itemsShow && index === i) {
for (let j = 0; j < this.menuInfo.length; j++) {
this.menuInfo[j].itemsShow = false
}
return
}
}
for (let i = 0; i < this.menuInfo.length; i++) {
this.menuInfo[i].itemsShow = false
}
this.menuInfo[index].itemsShow = true
},
// 导航大小按钮控制事件
showNavIcon () {
this.navShow = !this.navShow
this.$store.commit('cdeploy/changeWidth', this.navShow)
},
// 路由调转
routerTo (item) {
if (item.pathName) {
const obj = {
contentRouter: item.pathName,
id: item.pathName,
contentTitle: item.name
}
this.$router.push({
path: item.pathName
})
}
},
// hover效果
hoverInfo () {
this.hoverShow = !this.hoverShow
}
}
}
css
@import './clearfix.scss';
@import './scroller.scss';
.my-slider {
width: 220px;
background-color: #182132;
height: 100%;
padding-bottom: 113px;
font-size: 14px;
transition: all 300ms;
}
/* logo样式 */
.my-slider-icon-logo {
position: fixed;
top: 0;
left: 0;
z-index: 2;
.icon-logo {
position: absolute;
top: 0px;
left: 0px;
font-size: 52px;
width: 60px;
height: 60px;
background-color: #182132;
color: #2286ff;
text-align: center;
line-height: 60px;
}
.my-slider-content {
position: absolute;
top: 0;
left: 60px;
z-index: 2;
width: 160px;
background-color: #182132;
color: #a3acb9;
height: 60px;
line-height: 60px;
font-size: 18px;
font-weight: bold;
padding-left: 10px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
transition: all 300ms;
}
.my-slider-none {
width: 0px;
padding: 0px;
}
}
/* 底部操作按钮 */
.my-slider-back {
position: fixed;
bottom: 0;
left: 0;
width: 220px;
padding-left: 23px;
font-size: 14px;
color: #b2bfd2;
line-height: 42px;
border-top: 1px solid #232c3c;
cursor: pointer;
background-color: #182132;
z-index: 2;
transition: all 300ms;
}
/* content */
.my-nav {
height: 100%;
overflow: auto;
@include scroller(#e6e9ea, 0px);
transition: all 300ms;
}
.my-nav-child {
font-size: 14px;
position: relative;
cursor: pointer;
overflow: hidden;
transition: all 300ms;
}
.my-nav-a {
display: block;
color: #979ba5;
height: 42px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
position: relative;
&:hover {
color: #fff;
background-color: #303c4c;
.my-point {
background-color: #fff;
}
}
.my-icon-color {
font-size: 16px;
position: absolute;
top: 13px;
left: 23px;
}
.icon-angle-down,
.icon-angle-up {
font-size: 8px;
position: absolute;
top: 16px;
right: 20px;
}
.my-nav-span {
position: absolute;
top: 12px;
left: 68px;
}
.my-point {
width: 6px;
height: 6px;
display: inline-block;
border-radius: 50%;
background-color: #737987;
margin: 20px 0 2px 28px;
}
}
.my-nav-click {
background-color: #3c96ff;
a {
color: #fff;
.my-icon-color {
color: #fff;
}
.my-point {
background-color: #fff;
}
}
}
.my-nav-show {
background-color: #202a3c;
}
/* line */
.my-line-a {
text-align: center;
line-height: 42px;
color: #555c66;
&:hover {
color: #555c66;
background-color: #182132;
}
}
.my-left-line,
.my-right-line {
position: absolute;
height: 1px;
background-color: #555c66;
width: 45px;
top: 22px;
}
.my-left-line {
left: 7px;
}
.my-right-line {
right: 7px;
}
/* 小屏宽度 */
.my-slider-width {
width: 60px!important;
}
.my-hover-width {
position: absolute;
top: 0;
left: 0;
width: 220px!important;
}
效果图
优点
1:自定义导航中的icon
2:通过控制menuInfo这个对象来控制导航的生成,合理的参数变量来控制dom的操作
3:简易的动画效果
4:节约空间,方便用户使用
改进
1:代码写的有些冗余,可以简易优化一下
2:布局样式上也可以进行优化
更多推荐
已为社区贡献1条内容
所有评论(0)