框架布局
本章只介绍基础布局,和一些主要的 js,页面上基本上都是些交互事件,项目代码上都有注释,不懂的地方 debug 跑一变就知道了,只是这些事件基本上没有独立存在的,相互之间都有关联
框架风格
新建页面:/src/views/layout/layout.vue
<!– layout.vue –>
<template>
<div id=”loyout”>
<el-container>
<layoutAside></layoutAside>
<el-container>
<layoutHeader></layoutHeader>
<el-main id=”elmain”>
<transition name=”main” mode=”out-in”>
<router-view></router-view>
</transition>
</el-main>
<el-footer>
<Bottom></Bottom>
</el-footer>
</el-container>
</el-container>
</div>
</template>
aside 无限级菜单组件
新建页面:/src/views/layout/aside/aside.vue
<!– aside.vue –>
<template>
<div>
<el-aside id=”asideNav”>
<div class=”logo-name”>
<p v-if=”$store.getters.logoShow”>XU</p>
<p v-else>vue-xuAdmin 后台模板 </p>
</div>
<!– el-menu 的属性查看官方文档 –>
<el-menu :default-active=”$route.path” class=”el-menu-vertical”
@select=”selectmenu”
:collapse=”$store.getters.isCollapse”
background-color=”#03152A”
text-color=”rgba(255,255,255,.7)”
active-text-color=”#ffffff”
:router=”$store.getters.uniquerouter”
:unique-opened=”$store.getters.uniquerouter”
:collapse-transition=”true”
>
<!– 遍历根据权限生成的路由表生成菜单列表 –>
<template v-for=”(item,index) in $store.getters.routers” v-if=”!item.hidden”>
<!– 检查是否带有 alone 属性的一级菜单类似“主页”,还有子菜单的个数 –>
<el-submenu v-if=”!item.alone && item.children.length>0″ :index=”index+””>
<template slot=”title”>
<!– 如果没有设置图标将会采用默认图标‘fa fa-server’–>
<i :class=”item.iconCls?item.iconCls:[fa,fa-server]”></i>
<span slot=”title”>{{$t(`routeNmae.${item.name}`) }}</span>
</template>
<!– 子菜单组件 –>
<menu-tree :menuData=”item.children”></menu-tree>
</el-submenu>
<!– 一级菜单 –>
<el-menu-item :index=”item.path” v-else>
<i :class=”item.iconCls?item.iconCls:[fa,fa-file]”></i>
<span slot=”title”>{{$t(`routeNmae.${item.name}`) }}</span>
</el-menu-item>
</template>
</el-menu>
</el-aside>
</div>
</template>
点击菜单
// aside.vue
watch: {
// 监听浏览器直接输入路由,将此路由添加到 tabnavBox
‘$route.path’: function (val) {
this.selectmenu(val)
}
},
// 点击菜单把当前菜单的 name 和 path 添加到 tabNavBox 容器,生成 tabNav 标签页菜单
selectmenu (key) {
// 获取当前权限路由表
let router = this.$store.getters.routers
let name = ”
// 查找路由的 name 属性
let navTitle = function (path, routerARR) {
for (let i = 0; i < routerARR.length; i++) {
if (routerARR[i].children.length > 0 || routerARR[i].path === path) {
if (routerARR[i].path === path && routerARR[i].children.length < 1) {
name = routerARR[i].name
break
}
// 递归查找
navTitle(path, routerARR[i].children)
}
}
return name
}
// tabNavBox 添加数据
this.$store.dispatch(‘addTab’, {
title: navTitle(key, router),
path: key
})
}
子菜单组件 menu-true
新建页面:/src/views/layout/aside/menuTree.vue
<!– menuTree.vue –>
<template>
<div>
<template v-for=”(child,index) in menuData”>
<el-submenu v-if=”child.children.length > 0″ :index=”child.path”>
<template slot=”title”>
<i :class=”child.iconCls?child.iconCls:[fa,fa-file]”></i>
<span slot=”title”>{{$t(`routeNmae.${child.name}`) }}</span>
</template>
<!– 通过递归 menu-tree 生成无限级菜单 –>
<menu-tree :menuData=”child.children”></menu-tree>
</el-submenu>
<el-menu-item v-else :index=”child.path”>
<i :class=”child.iconCls?child.iconCls:[fa,fa-file]”></i>
<span slot=”title”>{{$t(`routeNmae.${child.name}`) }}</span>
</el-menu-item>
</template>
</div>
</template>
header 头部
这里没啥好说的,都是 html 布局,tabnav 接下来说,i18n 后面会讲
新建页面:/src/views/layout/header/header.vue
<!– header.vue –>
<template>
<div>
<el-header id=”header”>
<span class=”hideAside” @click=”collapse”><i class=”fa fa-indent fa-lg”></i></span>
<ul class=”personal”>
<li class=”fullScreen” @click=”fullScreen”>
<el-tooltip class=”item” effect=”dark” content=” 全屏 ” placement=”bottom”><i
class=”fa fa-arrows-alt fa-lg”></i></el-tooltip>
</li>
<li>
<langSelect></langSelect>
</li>
<li>{{$t(`role.${this.$store.getters.info.role}`) }}</li>
<li>
<el-dropdown @command=”handleCommand”>
<span class=”el-dropdown-link”>
夏洛克丶旭 <i class=”el-icon-arrow-down el-icon–right”></i>
</span>
<el-dropdown-menu slot=”dropdown”>
<el-dropdown-item command=”a”>{{$t(‘userDropdownMenu.basicInfor’) }}</el-dropdown-item>
<el-dropdown-item command=”b”>{{$t(‘userDropdownMenu.changePassword’) }}</el-dropdown-item>
<el-dropdown-item command=”logout” divided>{{$t(‘userDropdownMenu.logout’) }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</li>
<li class=”icon”><img :src=”avatar”/></li>
</ul>
</el-header>
<!– tabNav 组件, 标签页菜单 –>
<tabNav></tabNav>
</div>
</template>
tabNav 组件
这里的 tabNav 标签动画和页面的动画是一样的, 都是官方的 demo 稍微改一下,,只不过页面有 mode=”out-in” 所以动画时间需要快一点
新建页面:/src/views/layout/header/tabNav.vue
<!– tabNav.vue –>
<template>
<div>
<div class=”tabnavBox”>
<transition-group name=”list” tag=”ul”>
<!– tabnavBox 是存储所有 tabNav 的数据容器,每次点击左侧菜单就会把数据添加到 tabnavBox –>
<li v-for=”(item, index) in $store.getters.tabnavBox” @contextmenu.prevent=”openMenu(item,$event,index)”
:key=”item.title” class=”tabnav” :class=”{active: $route.path === item.path}”>
<router-link :to=”item.path”>{{$t(`routeNmae.${item.title}`) }}</router-link>
<i @click=”removeTab(item)” class=”el-icon-error” v-if=”index !== 0″></i>
</li>
</transition-group>
</div>
<!– 右击菜单 –>
<ul v-show=”this.rightMenuShow” :style=”{left:this.left+’px’,top:this.top+’px’}” class=”menuBox”>
<li @click=”removeTab($store.getters.rightNav)”><i class=”fa fa-remove”></i>{{$t(‘rightMenu.close’) }}</li>
<li @click=”removeOtherTab($store.getters.rightNav)”>{{$t(‘rightMenu.closeOther’) }}</li>
<li @click=”removeAllTab”>{{$t(‘rightMenu.closeAll’) }}</li>
</ul>
</div>
</template>