iview-admin动态路由实现过程

一、大致思路

1.后台接口返回路由数据,路由数据在后台添加完成,数据格式参考iview-admin路由配置。
2.前端拿到数据之后进行格式化处理。
3.在路由守卫处进行动态添加 addRoutes

二、实现过程

1.因为大部分路由从后台获取,所以本地routers.js文件只保留login、home、401、500等不需要权限控制的路由(404跟动态路由一同注入)。

{
		path: '/login',
		name: 'login',
		meta: {
			title: '登录',
			hideInMenu: true,
		},
		component: () => import('@/view/login/login.vue')
	}, {
		path: '/',
		name: '_data',
		redirect: '/data',
		component: Main,
		meta: {
			notCache: true,
			hideInBread: true
		},
		children: [{
			path: '/data',
			name: 'data',
			meta: {
				title: '收据统计',
				notCache: true,
				icon: 'md-stats'
			},
			component: () => import('@/view/data/data_statistics.vue')
		}]
	},
	{
		path: '/401',
		name: 'error_401',
		meta: {
			hideInMenu: true
		},
		component: () => import('@/view/error-page/401.vue')
	},
	{
		path: '/500',
		name: 'error_500',
		meta: {
			hideInMenu: true
		},
		component: () => import('@/view/error-page/500.vue')
	}
]

2.在libs文件夹下创建格式化路由数据的工具文件 router-util.js

3.在router-util.js里写入以下方法 

import {
	hasChild,
	localRead,
	getToken
} from '@/libs/util'
import store from '@/store'
import Main from '@/components/main'
import {
	forEach
} from '@/libs/tools'

// 加载菜单
export const loadMenu = () => {
	let list = []
	let data = localRead('route')
	if (!data) {
		return list
	}
	list = formatMenu(JSON.parse(data))
	return list
}

// 格式化菜单
export const formatMenu = (list) => {
	let res = []
	forEach(list, item => {
		let obj = {
			path: item.path,
			name: item.name
		}
		obj.meta = item.meta
		if (item.parentid === 0) {
			obj.component = Main
		} else {
			let data = item.component
			// 这里的data应为 /notice/notice.vue 类似的数据,对应的是src/view/下的本地文件
			obj.component = () => import('@/view' + data)
		}
		if (hasChild(item)) {
			obj.children = formatMenu(item.children)
		}
		res.push(obj)
	})
	return res
}

3.修改菜单展示数据,这里的数据保存在store/module/app.js下

①引入路由数据读取方法

import { loadMenu } from '@/libs/router-util'

②修改getters,将原本的menuList修改为下面的方法

// 通过路由列表得到菜单列表
menuList: (state, getters, rootState) => getMenuByRouter(loadMenu(),rootState.user.access),

③在mutations中添加下面方法

// 接受前台数组,刷新菜单
updateMenuList(state, routes) {
	router.addRoutes(routes);
	state.menuList = routes
},

4.处理路由守卫文件router/index.js,这里代码比较多我就都贴出来了
注意:这里我们不在使用iview-admin自带的turnTo方法,我在这里被卡了很久。

import Vue from 'vue'
import Router from 'vue-router'
import routes from './routers'
import store from '@/store'
import iView from 'iview'
import {
	setToken,
	getToken,
	setTitle,
	localSave,
	localRead
} from '@/libs/util'
import config from '@/config'
const {
	homeName
} = config

// 引入加载菜单
import {
	loadMenu,
	formatMenu
} from '@/libs/router-util'
import {
	routeindex	// 这里是封装的后台返回菜单数据的接口,方法名称根据实际情况改变
} from '@/api/setting'

Vue.use(Router)
const router = new Router({
	routes: [...routes, ...loadMenu()],
	mode: 'hash'  //这个一定要是 hash,如果是一定需要配置为history,请查看路由模式
})

const LOGIN_PAGE_NAME = 'login'

router.beforeEach((to, from, next) => {
	iView.LoadingBar.start()
	const token = getToken()
	const menu = localRead('route') // 读取路由数据
	if (!token && to.name !== LOGIN_PAGE_NAME) {
		// 未登录且要跳转的页面不是登录页
		next({
			name: LOGIN_PAGE_NAME // 跳转到登录页
		})
	} else if (!token && to.name === LOGIN_PAGE_NAME) {
		// 未登陆且要跳转的页面是登录页
		next() // 跳转
	} else if (token && to.name === LOGIN_PAGE_NAME) {
		// 已登录且要跳转的页面是登录页		
		next({
			name: homeName // 跳转到homeName页
		})
	} else {
		store.dispatch('getUserInfo').then(user => {
			// 如果本地不存在路由数据则动态获取
			if (!menu || menu.length === 0) {
				routeindex().then(res => {
					var list = []
					var menuData = res.data.data
					localSave('route', JSON.stringify(menuData))
					// 格式化菜单
					list = formatMenu(menuData)
					// 将404路由动态注入,防止第一次没有路由数据跳转到404,
					list.push({
						path: '*',
						name: 'error_404',
						meta: {
							hideInMenu: true
						},
						component: () => import('@/view/error-page/404.vue')
					})
					// 刷新界面菜单
					store.commit('updateMenuList', list)
					// next() 因为 router 版本的原因,现在改为下面这种方式。
                    router.push({path:homeName}).catch(err => { console.log(err) })
				})
			} else {
				next()
			}
		}).catch(() => {
			setToken('')
			next({
				name: 'login'
			})
		})
	}
})

router.afterEach(to => {
	setTitle(to, router.app)
	iView.LoadingBar.finish()
	window.scrollTo(0, 0)
})

export default router

本文转载:iview-admin动态路由实现过程_黑土地里的小萝卜的博客-CSDN博客_iview动态路由

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值