后台管理外框架demo,由vue + seajs架構的后台管理框架,頁面主要三部分組成:頭部、左側菜單、主界面。左側菜單以路由控制在主界面以tab頁形式展示。
seajs主要是用來做代碼組織的,方便模塊化加載。功能上實現主要是vue+elementUI+vuex。
左側導航(自定義app-nav組件)
整個框架使用elementUI實現界面,導航使用的是左側菜單組件-NavMenu導航菜單
將左側菜單導航單獨做成一個組件。
<!--html-->
<div class="app-nav-wrap">
//default-active設置當前激活的菜單。設置router使用 vue-router 的模式,啟用該模式會在激活導航時以 index 作為 path 進行路由跳轉
<el-menu :default-active="$route.path" class="el-menu-vertical-demo" router>
//index設置的值為path
<el-menu-item v-for="menu in menus" :index="menu.route" :key="menu.route" v-if="!menu.children">
<i class="el-icon-menu"></i>{{menu.name}}
</el-menu-item>
<el-submenu v-for="menu in menus" :index="menu.route" :key="menu.route" v-if="menu.children">
<template slot="title"><i class="el-icon-menu"></i>{{menu.name}}</template>
<el-menu-item :index="item.route" v-for="item in menu.children" :key="item.route"> <i class="el-icon-location"></i>{{item.name}}</el-menu-item>
</el-submenu>
</el-menu>
</div>
<!--菜單組件的js-->
//系統的菜單數據,渲染頁面顯示,靈活增刪菜單
//route作為路徑設置,name作為菜單名稱顯示,children作為是否有子菜單的判斷。
data() {
return {
menus: [
{ route: '/', name: '首頁' , children:false},
{ route: '/user', name: '用戶管理' , children:false},
{ route: '/psd', name: '密碼管理' , children:false},
{ route: '/salary', name: '工資管理' , children:false},
{ route: '/attendence', name: '考勤管理' , children:false},
{ route: '/perform', name: '績效考核', children: [{ route: '/month', name: '月度績效' }, { route: '/year', name: '年度績效' }] },
{ route: '/admin', name: '系統管理' , children:false},
{ route: '/feedback', name: '意見反饋' , children:false}
]
}
},
路由應該與上面組件中顯示的對應,否則不會跳轉。
<!--路由設置-->
const router = new VueRouter({
routes: [
{
path: '/',
name: '首頁',
component: main,
children: [
{
path: '/user',
name: '用戶管理',
component: ElementTable,
},
{
path: '/userInfo/:id',
name: '用戶詳情頁',
component: DetailInfo
},
{
path: '/psd',
name: '密碼管理',
component: Template
},
{
path: '/salary',
name: '工資管理',
component: Template
},
{
path: '/attendence',
name: '考勤管理',
component: Template
},
{
path: '/perform',
name: '績效考核',
component: Template,
children:[
{
path: '/month',
name: '月度績效',
component: Monthform
},
{
path:'/year',
name: '年度績效',
component: Theform
}
]
},
{
path: '/admin',
name: '系統管理',
component: Template
},
{
path: '/feedback',
name: '意見反饋',
component: Template
}
]
},
{
path: '*',
redirect: '/'
}
]
});
以上實現點擊菜單項頁面跳轉到對應的路由頁面。
路由跳轉顯示tab頁面(main框架組件)
在框架組件中,采用watch監聽頁面路由改變(即點擊菜單操作),新增路由添加tab頁,點擊已打開的路由則跳轉到相應的tab頁。
watch: {
'$route'(to) {
let flag = false;//判斷是否頁面中是否已經存在該路由下的tab頁
//options記錄當前頁面中已存在的tab頁
for (let option of this.options) {
//用名稱匹配,如果存在即將對應的tab頁設置為active顯示桌面前端
if (option.name === to.name) {
flag = true;
this.$store.commit('set_active_index', '/' + to.path.split('/')[1]);
break;
}
}
//如果不存在,則新增tab頁,再將新增的tab頁設置為active顯示在桌面前端
if (!flag) {
this.$store.commit('add_tabs', { route: '/' + to.path.split('/')[1], name: to.name });
this.$store.commit('set_active_index', '/' + to.path.split('/')[1]);
}
}
}
來看一下框架組件的html,將菜單組件app-nav引入,主界面為tab欄。
使用elementUI的tab組件,綁定activeIndex為激活tab頁顯示在桌面前端,利用for循環options顯示所有已打開的tab頁。
<div class="main">
<div class="app-header">
<div class="title">后台管理系統</div>
</div>
<div class="app-content">
<div class="app-nav">
<app-nav></app-nav>
</div>
<div class="app-wrap">
<!-- 此處放置el-tabs代碼 -->
<div class="template-tabs">
<el-tabs v-model="activeIndex" type="border-card" closable @tab-click="tabClick" v-if="options.length" @tab-remove="tabRemove">
<el-tab-pane :key="item.name" v-for="(item, index) in options" :label="item.name" :name="item.route">
</el-tab-pane>
</el-tabs>
</div>
<div class="content-wrap">
<keep-alive>
<router-view/>
</keep-alive>
</div>
</div>
</div>
</div>
綁定兩個主要函數:
- tabClick----點擊tab標簽將其激活顯示在桌面最前端;
- tabRemove-----點擊tab標簽中的關閉按鈕,將當前tab頁關閉並從options里面移除。
對應的函數為:
methods: {
// tab切換時,動態的切換路由
tabClick(tab) {
let path = this.activeIndex;
// 用戶詳情頁的時候,對應了二級路由,需要拼接添加第二級路由
if (this.activeIndex === '/userInfo') {
path = this.activeIndex + '/' + this.$store.state.userInfo.name;
}
this.$router.push({ path: path });//路由跳轉
},
tabRemove(targetName) {
// 首頁不可刪除
if (targetName == '/') {
return;
}
//將改tab從options里移除
this.$store.commit('delete_tabs', targetName);
//還同時需要處理一種情況當需要移除的頁面為當前激活的頁面時,將上一個tab頁作為激活tab
if (this.activeIndex === targetName) {
// 設置當前激活的路由
if (this.options && this.options.length >= 1) {
this.$store.commit('set_active_index', this.options[this.options.length - 1].route);
this.$router.push({ path: this.activeIndex });
} else {
this.$router.push({ path: '/' });
}
}
}
},
computed: {
options() {
return this.$store.state.options;
},
//動態設置及獲取當前激活的tab頁
activeIndex: {
get() {
return this.$store.state.activeIndex;
},
set(val) {
this.$store.commit('set_active_index', val);
}
}
}
上述邏輯中采用了vuex存儲tab數據,options維護一個數組,存儲已經打開的tab頁,activeIndex保存當前激活的tab頁。
-
add_tabs:添加新的tab頁,向options數組中添加新數據。
-
delete_tabs:關閉tab頁,並將其從options數組中移除。
-
set_active_index:設置當前激活的tab。
/**
* Vuex全局狀態管理
* @param options {Array} 用於渲染tabs的數組
*/
const store = new Vuex.Store({
state: {
options: [],
activeIndex: '/user'
},
mutations: {
// 添加tabs
add_tabs(state, data) {
this.state.options.push(data);
},
// 刪除tabs
delete_tabs(state, route) {
let index = 0;
for (let option of state.options) {
if (option.route === route) {
break;
}
index++;
}
this.state.options.splice(index, 1);
},
// 設置當前激活的tab
set_active_index(state, index) {
this.state.activeIndex = index;
},
}
});