Skip to content

Commit

Permalink
动态菜单路由完成
Browse files Browse the repository at this point in the history
  • Loading branch information
daxiongYang committed Apr 29, 2018
1 parent 80d6867 commit b5175bf
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 176 deletions.
6 changes: 3 additions & 3 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import '@/element-ui'
import '@/icons'
import '@/assets/scss/index.scss'

import http from '@/utils/http'
import httpRequest from '@/utils/httpRequest'
import { isAuth } from '@/utils'

Vue.use(VueCookie)
Expand All @@ -20,8 +20,8 @@ if (process.env.NODE_ENV !== 'production') {
require('@/mock')
}

Vue.prototype.$http = http // 挂载, ajax请求方法
Vue.prototype.isAuth = isAuth // 挂载, 权限方法
Vue.prototype.$http = httpRequest // 挂载, ajax请求方法
Vue.prototype.isAuth = isAuth // 挂载, 权限方法

/* eslint-disable no-new */
new Vue({
Expand Down
2 changes: 1 addition & 1 deletion src/mock/create.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Mock from 'mockjs'
import http from '@/utils/http'
import http from '@/utils/httpRequest'
import merge from 'lodash/merge'

/**
Expand Down
55 changes: 37 additions & 18 deletions src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
*/
import Vue from 'vue'
import Router from 'vue-router'
import http from '@/utils/http'
import http from '@/utils/httpRequest'
import { isURL } from '@/utils/validate'

Vue.use(Router)

Expand All @@ -15,8 +16,8 @@ const _import = require('./import-' + process.env.NODE_ENV)

// 全局路由(无需嵌套上左右整体布局)
const globalRoutes = [
{ path: '/404', component: _import('common/404'), name: '404', desc: '404未找到' },
{ path: '/login', component: _import('common/login'), name: 'login', desc: '登录' }
{ path: '/404', component: _import('common/404'), name: '404', meta: { title: '404未找到' } },
{ path: '/login', component: _import('common/login'), name: 'login', meta: { title: '登录' } }
]

// 主入口路由(需嵌套上左右整体布局)
Expand All @@ -25,10 +26,23 @@ const mainRoutes = {
component: _import('main'),
name: 'main',
redirect: { name: 'home' },
desc: '主入口整体布局',
meta: { title: '主入口整体布局' },
children: [
{ path: '/home', component: _import('common/home'), name: 'home', desc: '首页' },
{ path: '/theme', component: _import('common/theme'), name: 'theme', desc: '主题' }
// 通过meta对象设置路由展示方式
// 1. isTab: 是否通过tab展示内容, true: 是, false: 否
// 2. iframeUrl: 是否通过iframe嵌套展示内容, '以http[s]://开头': 是, '': 否
{ path: '/home', component: _import('common/home'), name: 'home', meta: { title: '首页' } },
{ path: '/theme', component: _import('common/theme'), name: 'theme', meta: { title: '主题' } },
{
path: '/demo-01',
component: null, // 如需要通过iframe嵌套展示内容, 但不通过tab打开, 请自行创建组件使用iframe处理!
name: 'demo-01',
meta: {
title: '我是一个通过iframe嵌套展示内容, 并通过tab打开 demo',
isTab: true,
iframeUrl: 'http://fast.demo.renren.io/'
}
}
],
beforeEnter (to, from, next) {
let token = Vue.cookie.get('token')
Expand All @@ -42,15 +56,15 @@ const mainRoutes = {
const router = new Router({
mode: 'hash',
scrollBehavior: () => ({ y: 0 }),
isAddDynamicRoutes: false, // 是否已经添加动态(菜单)路由
isAddDynamicMenuRoutes: false, // 是否已经添加动态(菜单)路由
routes: globalRoutes.concat(mainRoutes)
})

router.beforeEach((to, from, next) => {
// 添加动态(菜单)路由
// 1. 已经添加 or 全局路由, 直接访问
// 2. 获取菜单列表, 添加并保存本地存储
if (router.options.isAddDynamicRoutes || fnCurrentRouteType(to) === 'global') {
if (router.options.isAddDynamicMenuRoutes || fnCurrentRouteType(to) === 'global') {
next()
} else {
http({
Expand All @@ -59,8 +73,8 @@ router.beforeEach((to, from, next) => {
params: http.adornParams()
}).then(({data}) => {
if (data && data.code === 0) {
fnAddDynamicRoutes(data.menuList)
router.options.isAddDynamicRoutes = true
fnAddDynamicMenuRoutes(data.menuList)
router.options.isAddDynamicMenuRoutes = true
sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]'))
sessionStorage.setItem('permissions', JSON.stringify(data.permissions || '[]'))
} else {
Expand Down Expand Up @@ -93,7 +107,7 @@ function fnCurrentRouteType (route) {
* @param {*} menuList 菜单列表
* @param {*} routes 递归创建的动态(菜单)路由
*/
function fnAddDynamicRoutes (menuList = [], routes = []) {
function fnAddDynamicMenuRoutes (menuList = [], routes = []) {
var temp = []
for (var i = 0; i < menuList.length; i++) {
if (menuList[i].list && menuList[i].list.length >= 1) {
Expand All @@ -103,14 +117,19 @@ function fnAddDynamicRoutes (menuList = [], routes = []) {
path: menuList[i].url.replace('/', '-'),
component: null,
name: menuList[i].url.replace('/', '-'),
desc: menuList[i].name,
meta: { menuId: menuList[i].menuId, isTab: true }
meta: {
menuId: menuList[i].menuId,
title: menuList[i].name,
isDynamic: true,
isTab: true,
iframeUrl: ''
}
}
// url以http[s]?开头, 通过iframe展示
if (/^http[s]?:\/\/.*/.test(menuList[i].url)) {
// url以http[s]://开头, 通过iframe展示
if (isURL(menuList[i].url)) {
route['path'] = `i-${menuList[i].menuId}`
route['name'] = `i-${menuList[i].menuId}`
route['meta']['isIframe'] = true
route['meta']['iframeUrl'] = menuList[i].url
} else {
try {
route['component'] = _import(`modules/${menuList[i].url}`) || null
Expand All @@ -120,15 +139,15 @@ function fnAddDynamicRoutes (menuList = [], routes = []) {
}
}
if (temp.length >= 1) {
fnAddDynamicRoutes(temp, routes)
fnAddDynamicMenuRoutes(temp, routes)
} else {
mainRoutes.name = 'main-dynamic'
mainRoutes.children = routes
router.addRoutes([
mainRoutes,
{ path: '*', redirect: { name: '404' } }
])
sessionStorage.setItem('dynamicRoutes', JSON.stringify(mainRoutes.children || '[]'))
sessionStorage.setItem('dynamicMenuRoutes', JSON.stringify(mainRoutes.children || '[]'))
console.log('\n%c!<-------------------- 动态(菜单)路由 s -------------------->', 'color:blue')
console.log(mainRoutes.children)
console.log('%c!<-------------------- 动态(菜单)路由 e -------------------->\n\n', 'color:blue')
Expand Down
File renamed without changes.
8 changes: 8 additions & 0 deletions src/utils/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,11 @@ export function isMobile (s) {
export function isPhone (s) {
return /^([0-9]{3,4}-)?[0-9]{7,8}$/.test(s)
}

/**
* URL地址
* @param {*} s
*/
export function isURL (s) {
return /^http[s]?:\/\/.*/.test(s)
}
126 changes: 126 additions & 0 deletions src/views/main-content.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<template>
<main class="site-content" :class="{ 'site-content--tabs': $route.meta.isTab }">
<!-- 主入口标签页 s -->
<el-tabs
v-if="$route.meta.isTab"
v-model="mainTabsActiveName"
:closable="true"
@tab-click="selectedTabHandle"
@tab-remove="removeTabHandle">
<el-dropdown class="site-tabs__tools" :show-timeout="0">
<i class="el-icon-arrow-down el-icon--right"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="tabsCloseCurrentHandle">关闭当前标签页</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseOtherHandle">关闭其它标签页</el-dropdown-item>
<el-dropdown-item @click.native="tabsCloseAllHandle">关闭全部标签页</el-dropdown-item>
<el-dropdown-item @click.native="tabsRefreshCurrentHandle">刷新当前标签页</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-tab-pane
v-for="item in mainTabs"
:key="item.name"
:label="item.title"
:name="item.name">
<el-card :body-style="siteContentViewHeight">
<iframe
v-if="item.type === 'iframe'"
:src="item.iframeUrl"
width="100%" height="100%" frameborder="0" scrolling="yes">
</iframe>
<keep-alive v-else>
<router-view v-if="item.name === mainTabsActiveName" />
</keep-alive>
</el-card>
</el-tab-pane>
</el-tabs>
<!-- 主入口标签页 e -->
<el-card v-else :body-style="siteContentViewHeight">
<keep-alive>
<router-view />
</keep-alive>
</el-card>
</main>
</template>

<script>
import { isURL } from '@/utils/validate'
export default {
data () {
return {
}
},
computed: {
documentClientHeight: {
get () { return this.$store.state.common.documentClientHeight }
},
menuActiveName: {
get () { return this.$store.state.common.menuActiveName },
set (val) { this.$store.commit('common/updateMenuActiveName', val) }
},
mainTabs: {
get () { return this.$store.state.common.mainTabs },
set (val) { this.$store.commit('common/updateMainTabs', val) }
},
mainTabsActiveName: {
get () { return this.$store.state.common.mainTabsActiveName },
set (val) { this.$store.commit('common/updateMainTabsActiveName', val) }
},
siteContentViewHeight () {
var height = this.documentClientHeight - 50 - 30 - 2
if (this.$route.meta.isTab) {
height -= 40
return isURL(this.$route.meta.iframeUrl) ? { height: height + 'px' } : { minHeight: height + 'px' }
}
return { minHeight: height + 'px' }
}
},
methods: {
// tabs, 选中tab
selectedTabHandle (tab) {
tab = this.mainTabs.filter(item => item.name === tab.name)
if (tab.length >= 1) {
this.$router.push({ name: tab[0].name })
}
},
// tabs, 删除tab
removeTabHandle (tabName) {
var newTabs = this.mainTabs.filter(item => item.name !== tabName)
if (newTabs.length >= 1) {
// 当前选中tab被删除
if (tabName === this.mainTabsActiveName) {
this.$router.push({ name: newTabs[newTabs.length - 1].name }, () => {
this.mainTabsActiveName = this.$route.name
})
}
this.mainTabs = newTabs
} else {
this.menuActiveName = ''
this.$router.push({ name: 'home' })
}
},
// tabs, 关闭当前
tabsCloseCurrentHandle () {
this.removeTabHandle(this.mainTabsActiveName)
},
// tabs, 关闭其它
tabsCloseOtherHandle () {
this.mainTabs = this.mainTabs.filter(item => item.name === this.mainTabsActiveName)
},
// tabs, 关闭全部
tabsCloseAllHandle () {
this.mainTabs = []
this.menuActiveName = ''
this.$router.push({ name: 'home' })
},
// tabs, 刷新当前
tabsRefreshCurrentHandle () {
var tempTabName = this.mainTabsActiveName
this.removeTabHandle(tempTabName)
this.$nextTick(() => {
this.$router.push({ name: tempTabName })
})
}
}
}
</script>

6 changes: 3 additions & 3 deletions src/views/main-sidebar-sub-menu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
v-for="item in menu.list"
:key="item.menuId"
:menu="item"
:dynamicRoutes="dynamicRoutes">
:dynamicMenuRoutes="dynamicMenuRoutes">
</sub-menu>
</el-submenu>
<el-menu-item v-else :index="menu.menuId + ''" @click="gotoRouteHandle(menu)">
Expand All @@ -26,7 +26,7 @@
type: Object,
required: true
},
dynamicRoutes: {
dynamicMenuRoutes: {
type: Array,
required: true
}
Expand All @@ -37,7 +37,7 @@
methods: {
// 通过menuId与动态(菜单)路由进行匹配跳转至指定路由
gotoRouteHandle (menu) {
var route = this.dynamicRoutes.filter(item => item.meta.menuId === menu.menuId)
var route = this.dynamicMenuRoutes.filter(item => item.meta.menuId === menu.menuId)
if (route.length >= 1) {
this.$router.push({ name: route[0].name })
}
Expand Down
Loading

0 comments on commit b5175bf

Please sign in to comment.