vue-element-admin-master框架使用

在线预览

https://github.com/PanJiaChen/vue-element-admin/blob/master/README.zh-CN.md       (总连接)

 使用文档

一、细节注意点及代码分析

1.settings.js 文件


  1.showSettings: false,//右边设置 是否关闭

  2.tagsView: false,导航栏是否关闭

  3.fixedHeader: false,

  4.sidebarLogo: true,左边菜单顶部是否显示标题和logo

 2.登录逻辑 权限控制  代码分析

A. permission.js 是权限控制的 (其实就是路由拦截器)登录逻辑

import router from './router'
import store from './store'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar一个进度条的插件
import 'nprogress/nprogress.css' // progress bar style
import { getToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'

NProgress.configure({ showSpinner: false }) // NProgress Configuration 是否有转圈效果

const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist 没有重定向白名单

router.beforeEach(async (to, from, next) => {
	// 开始进度条
	NProgress.start()

	// 设置页面标题
	document.title = getPageTitle(to.meta.title)

	// 确定用户是否已登录
	const hasToken = getToken()

	if (hasToken) {
		if (to.path === '/login') {
			// 如果已登录,则重定向到主页
			next({ path: '/' })
			NProgress.done()
		} else {
			// determine whether the user has obtained his permission roles through getInfo
			const hasRoles = store.getters.roles && store.getters.roles.length > 0
			if (hasRoles) {
				//有用户信息
				next()
			} else {
				//无用户信息
				try {
					// 获得用户信息 实际是请求用户信息后返回,这里是模拟数据,直接从store中取
					// note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
					const { roles } = await store.dispatch('user/getInfo')

					// generate accessible routes map based on roles  
                    //方法generateRoutes在store/modules/permission.js 
					const accessRoutes = await store.dispatch('permission/generateRoutes', roles)//生成可访问的路由表

					// dynamically add accessible routes
					router.addRoutes(accessRoutes) //动态添加可访问路由表

					// hack method to ensure that addRoutes is complete
					// set the replace: true, so the navigation will not leave a history record
					next({ ...to, replace: true })  //hack方法 确保addRoutes已完成 
				} catch (error) {
					//  删除token,进入登录页面重新登录
					await store.dispatch('user/resetToken')
					Message.error(error || 'Has Error')
					next(`/login?redirect=${to.path}`)
					NProgress.done()
				}
			}
		}
	} else {
		/* has no token*/

		if (whiteList.indexOf(to.path) !== -1) {
			// in the free login whitelist, go directly 在免费登录白名单,直接去
			next()
		} else {
			// other pages that do not have permission to access are redirected to the login page.
			//没有访问权限的其他页面被重定向到登录页面。
			next(`/login?redirect=${to.path}`)
			NProgress.done()
		}
	}
})

router.afterEach(() => {
	// finish progress bar完成进度条
	NProgress.done()
})
/*
有token:再看看是不是去登录页的,登录页肯定不能拦截的,如果是登录页就直接放行。如果不是登录页,就要看看本地有没有用户信息,看看cookie中有没有用户信息(不一定是token,也可能是localstorage)。如果有用户信息,放行。如果没有用户信息,就调用接口去获取登录信息,然后后面还有一点代码,涉及到了动态添加路由(这里先说到这,后面具体说动态添加权限路由的事)。获取到用户信息后放行。如果在获取用户信息的过程中报错,则回到登录页

无token:先看看用户要进入的页面是不是在白名单内,一般登录、注册、忘记密码都是在白名单内的,这些页面,在无token的情况下也是直接放行。如果不在白名单内,滚回登录页。
 */

2.router

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

/* 这是框 */
import Layout from '@/layout'

/*添加的路由模块 */
import componentsRouter from './modules/components'
import chartsRouter from './modules/charts'
import tableRouter from './modules/table'
import nestedRouter from './modules/nested'

/**
 * Note: sub-menu only appear when route children.length >= 1
 * 注意: 子菜单只在路由子菜单时长度> = 1的时候出现
 * 参考网址: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
 *
 * hidden: true                   如果设置为true,项目将不会显示在侧栏中(默认为false)
 * alwaysShow: true               如果设置为true,将始终显示根菜单
 *                                如果不设置alwaysShow, 当项目有多个子路由时,它将成为嵌套模式,否则不显示根菜单
 * redirect: noRedirect           如果设置noRedirect,则不会在面包屑中重定向
 * name:'router-name'             the name is used by  (must set!!!)
 * meta : {
    roles: ['admin','editor']    控制页面角色(可以设置多个角色)'admin','editor'
    title: 'title'               名称显示在侧边栏和面包屑(推荐集)
    icon: 'svg-name'             图标显示在侧栏中
    breadcrumb: false            如果设置为false,则该项将隐藏在breadcrumb中(默认为true)
    activeMenu: '/example/list'  如果设置路径,侧栏将突出显示您设置的路径
  }
 */

/**
 * constantRoutes
 * a base page that does not have permission requirements
 * all roles can be accessed
 *	没有权限要求的基本页
 * 所有角色都可以访问
 * 不需要动态判断权限的路由
 */
export const constantRoutes = [
	{
		path: '/redirect',
		component: Layout,
		hidden: true,
		children: [
			{
				path: '/redirect/:path*',
				component: () => import('@/views/redirect/index')
			}
		]
	},
	{
		path: '/login',
		component: () => import('@/views/login/index'),
		hidden: true
	},
	{
		path: '/auth-redirect',
		component: () => import('@/views/login/auth-redirect'),
		hidden: true
	},
	{
		path: '/404',
		component: () => import('@/views/error-page/404'),
		hidden: true
	},
	{
		path: '/401',
		component: () => import('@/views/error-page/401'),
		hidden: true
	},
	{
		path: '/',
		component: Layout,
		redirect: '/dashboard',
		children: [
			{
				path: 'dashboard',
				component: () => import('@/views/dashboard/index'),
				name: 'Dashboard',
				meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
			}
		]
	},
	{
		path: '/documentation',
		component: Layout,
		children: [
			{
				path: 'index',
				component: () => import('@/views/documentation/index'),
				name: 'Documentation',
				meta: { title: 'Documentation', icon: 'documentation', affix: true }
			}
		]
	}
    ...
]

/**
 * asyncRoutes
 * the routes that need to be dynamically loaded based on user roles
 * 异步挂载的路由
 * 动态需要根据权限加载的路由表 
 */
export const asyncRoutes = [
	{
		path: '/permission',
		component: Layout,
		redirect: '/permission/page',
		alwaysShow: true, // will always show the root menu
		name: 'Permission',
		meta: {
			title: 'Permission',
			icon: 'lock',
			roles: ['admin', 'editor'] // you can set roles in root nav
		},
		children: [
			{
				path: 'page',
				component: () => import('@/views/permission/page'),
				name: 'PagePermission',
				meta: {
					title: 'Page Permission',
					roles: ['admin'] // or you can only set roles in sub nav
				}
			},
			{
				path: 'directive',
				component: () => import('@/views/permission/directive'),
				name: 'DirectivePermission',
				meta: {
					title: 'Directive Permission'
					// if do not set roles, means: this page does not require permission
				}
			},
			{
				path: 'role',
				component: () => import('@/views/permission/role'),
				name: 'RolePermission',
				meta: {
					title: 'Role Permission',
					roles: ['admin']
				}
			}
		]
	},
    ...
	// 404页面必须放在最后
	{ path: '*', redirect: '/404', hidden: true }
]
//创建路由
const createRouter = () => new Router({
	// mode: 'history', // require service support
	scrollBehavior: () => ({ y: 0 }),
	routes: constantRoutes
})

const router = createRouter()
// 重置路由
//参考网址: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
	const newRouter = createRouter()
	router.matcher = newRouter.matcher // reset router
}

export default router

/***
 *
 *  constantRoutes 和 asyncRoutes这2个是routes中分两块路由配置,一块是固定的,无权限的路由配置,也就是不管是管理员身份,还是超级管理员身份,都会显示的路由配置。
第二块是,带权限的路由配置,根据用户权限来显示侧边栏。注意,带权限的配置里的meta中都有role项,代表是权限
 */

 

参考材料 

二、业务操作

1.主菜单的字体图标更改

首先可以去阿里下载svg图片,放在src/icons/svg的文件里,然后在路由菜单中icon设置svg的名称(icon: 'reconciliation')

2.基于vue-admin-template-master框架开发 :权限控制

      一般说来,权限管理可以分为两种情况:第一种为页面级访问权限(菜单权限),第二种为数据级操作权限(按钮权限)。第一种情况是非常常见的,即用户是否能够看到页面;第二种情况是用户能否对数据进行增删改查等操作。
     前端的权限控制实质上就是用于展示,让操作变得更加友好,真正的安全实际上是由后端控制的。

登录拦截,动态路由

A.router 路由配置: constantRoutes 和 asyncRoutes设置

//公共路由
export const constantRoutes = [
	{
		path: '/login',
		component: () => import('@/views/login/index'),
		hidden: true
	},
	...
	{
		path: 'external-link',
		component: Layout,
		children: [
			{
				path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
				meta: { title: 'External Link', icon: 'link' }
			}
		]
	},


]

//动态路由
export const asyncRoutes = [
	{
		path: '/permission',
		component: Layout,
		redirect: '/permission/page',
		alwaysShow: true, // will always show the root menu
		name: 'Permission',
		meta: {
			title: '权限测试页',
			icon: 'lock',
			roles: ['admin', 'editor'] // you can set roles in root nav
		},
		children: [
			{
				path: 'role',
				component: () => import('@/views/permission/role'),
				name: 'RolePermission',
				meta: {
					title: '角色权限',
					roles: ['admin']
				}
			},
			{
				path: 'page',
				component: () => import('@/views/permission/page'),
				name: 'PagePermission',
				meta: {
					title: '页面权限',
					roles: ['admin'] // or you can only set roles in sub nav
				}
			},
			{
				path: 'directive',
				component: () => import('@/views/permission/directive'),
				name: 'DirectivePermission',
				meta: {
					title: '指令权限'
					// if do not set roles, means: this page does not require permission
				}
			}
		]
	},
	// 404 一定要放最后面
	{ path: '*', redirect: '/404', hidden: true }

]

B.permission.js 访问  获取动态的路由

vue-element-admin-master框架使用_第1张图片

在store请求接口 获取路由数据 :store/modules/permission.js

import { asyncRoutes, constantRoutes } from '@/router'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
    if (route.meta && route.meta.roles) {
        return roles.some(role => route.meta.roles.includes(role))
    } else {
        return true
    }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
    const res = []

    routes.forEach(route => {
        const tmp = { ...route }
        if (hasPermission(roles, tmp)) {
            if (tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, roles)
            }
            res.push(tmp)
        }
    })

    return res
}

const state = {
    routes: [],
    addRoutes: []
}

const mutations = {
    SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
    }
}

const actions = {
    /*
	roles是用户所带的权限
	这个方法就是把动态路由配置里符合用户权限的配置筛选出来,组成一个数组,然后,和固定路由合并到了一起,存到了vuex中
	*/
    generateRoutes({ commit }, roles) {
        return new Promise(resolve => {
            let accessedRoutes;
            if (roles.includes('admin')) {
                accessedRoutes = asyncRoutes || []
            } else {
                accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
            }
            // 生成左侧导航菜单
            commit('SET_ROUTES', accessedRoutes)
            resolve(accessedRoutes)
        })
    }
}

export default {
    namespaced: true,
    state,
    mutations,
    actions
}

 把值存在state里面

store/index.js


import permission from './modules/permission'

const store = new Vuex.Store({
	modules: {
		permission
	},
	getters
})


store/getters.js


const getters = {
	roles: state => state.user.roles,//角色
	permission_routes: state => state.permission.routes,//动态路由
}
export default getters

C.渲染页面components /sidebar /index.vue




...mapGetters(["permission_routes"]),

(1).页面权限(菜单权限):通过roles: ['admin']这个来区别不同角色访问不同页面

(2).按钮控制权限: 通过permission: ['add', 'edit']这个来判断不同角色可以操作不同的按钮

在路由里面配置

export const asyncRoutes = [
	{
		path: '/btnPermission',
		component: Layout,
		children: [
			{
				path: 'index',
				name: 'btnPermission',
				component: () => import('@/views/btnPermission/index'),
				meta: { title: '按钮控制页面显示', icon: 'form', permission: ['add', 'edit'] }
			}
		]
	},
]

directive/hasPermission/index.js封装一个指令的函数

const hasPermissionBtn = {
	inserted(el, binding, vnode) {
		const { value } = binding;
		let permissionList = vnode.context.$route.meta.permission;
		if (value && value instanceof Array && value.length > 0) {
			const permissionRoles = value;

			const hasPermission = permissionList.some(role => {
				return permissionRoles.includes(role);
			})
			if (!hasPermission) {
				el.parentNode && el.parentNode.removeChild(el);
			}
		}
	}
}
const install = function (Vue) {
	Vue.directive('hasPermissionBtn', hasPermissionBtn)
}

if (window.Vue) {
	window['hasPermissionBtn'] = hasPermissionBtn
	Vue.use(install); // eslint-disable-line
}

hasPermissionBtn.install = install;

export default hasPermissionBtn

 views\btnPermission/index.vue:页面操作





3.省市区 选择

git逛网  案例

安装:npm install element-china-area-data -S






绑定值:{{selectedOptions2}}
区域码转汉字:{{CodeToText[selectedOptions2[0]]}},{{CodeToText[selectedOptions2[1]]}},{{CodeToText[selectedOptions2[2]]}}
汉字转区域码:{{convertTextToCode(CodeToText[selectedOptions2[0]], CodeToText[selectedOptions2[1]], CodeToText[selectedOptions2[2]])}}

vue-element-admin-master框架使用_第2张图片

三、问题

1.element-ui的el-form验证和el-dialog关闭时清除验证

使用清除验证this.$refs.formName.clearValidate(); 

 

你可能感兴趣的:(vue-element-admin-master框架使用)