vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。[1]
vueAdmin-template 主要是基于vue-cli webpack模板为基础开发的,引入了如下dependencies:
element-ui 饿了么出品的vue2.0 pc UI框架axios 一个现在主流并且很好用的请求库 支持Promisejs-cookie 一个轻量的JavaScript库来处理cookienormalize.css 格式化cssnprogress 轻量的全局进度条控制vuex 官方状态管理vue-router 官方路由该项目只做了一个管理后台需要极简的功能,封装了axios请求,支持无限层级路由,动态权限和动态侧边栏。
本项目的定位是后台集成方案,不太适合当基础模板来进行二次开发。因为本项目集成了很多你可能用不到的功能,会造成不少的代码冗余。如果你的项目不关注这方面的问题,也可以直接基于它进行二次开发。
花裤衩建议
你可以把 vue-element-admin当做工具箱或者集成方案仓库,在 vue-admin-template 的基础上进行二次开发,想要什么功能或者组件就去 vue-element-admin 那里复制过来。
vue-admin-template/src下的目录结构: . ├── App.vue //入口 ├── api // 各种接口 ├── assets // 图片等资源 ├── components // 各种公共组件,非公共组件在各自view下维护 ├── icons //svg icon ├── main.js //入口 ├── permission.js //认证入口 ├── router // 路由表 ├── store // 存储 ├── styles // 各种样式 ├── utils // 公共工具,非公共工具,在各自view下维护 └── views // 各种layout
登录与权限控制
菜单及其动态菜单
图表展现
图标
色彩搭配
中文处理
跨域问题
按花裤衩的建议,使用vue-element-template为基础,进行二次开发。我们避免重复造轮子,尽量少改源代码,尽量抽取移植vue-element-admin工程内容,重新生成属于自己可控的开源框架平台。
根据Vue给定文件目录结构,我们重点选定如下内容:
功能点专业名称使用文件夹/文件说明菜单路由/src/router/index.js菜单与路由控制登录/src/views/login/index.vue登录控制获取权限权限控制/src/permission.js与路由配合控制转向我们可以这样理解vue-element-template工程(含权限控制版),vue-element-template只是包括菜单、路由、权限、API接口的基础集成,解决最基本的登录、权限、Token、菜单等最基本需求,其他扩展可以参考大而全的案例vue-element-admin,按需移植过来。
避免啰嗦和干扰,直接把/src/router/index.js中不需要的内容删除,结果如下:
export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, redirect: '/newdashboard', children: [{ path: 'newdashboard', name: 'NewDashboard', component: () => import('@/views/newdashboard/index'), meta: { title: '首页', icon: 'dashboard' } }] } ]如果有人要做国际化可以去element官网国际化看看写的很详细。 修改/src/main.js文件:
import locale from 'element-ui/lib/locale/lang/en' // lang i18n Vue.use(ElementUI, { locale })替换en为zh-CN
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n对于中文菜单,直接在路由的文件(/src/router/index.js),修改meta中title的描述为中文即可。
path: '/opeff', component: Layout, redirect: '/opeff/eff', name: 'OpEff', meta: { title: '作业效率分析', icon: 'money' },在当前菜单框架下,直接编辑路由文件(/src/router/index.js),按其树装结构和格式编写即可,效果如下:
export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, redirect: '/newdashboard', children: [{ path: 'newdashboard', name: 'NewDashboard', component: () => import('@/views/newdashboard/index'), meta: { title: '首页', icon: 'dashboard' } }] }, { path: '/opeff', component: Layout, redirect: '/opeff/eff', name: 'OpEff', meta: { title: '作业效率分析', icon: 'money' }, children: [ { path: 'eff', name: 'Eff', component: () => import('@/views/opeff/eff/index'), meta: { title: '效率综合分析', icon: 'eye-open' } }, { path: 'outlet', name: 'Outlet', component: () => import('@/views/opeff/outlet/index'), meta: { title: '发油效率分析', icon: 'link' } } ] } ]注:对于动态菜单,按权限控制菜单,由于文章逻辑和篇幅有限,先行略过,后续文章再写。
这里所说的新增页面,是指与新增菜单配套的页面,首先,根据上文菜单,在/src/views目录下形成如下文件夹结构: 在view目录下新增newdashboard目录,内新增index.vue, 作为改页面的入口。 /src/views/newdashboard/index.vue 拷贝vue-element-admin-master/src/views/dashboard/admin/index.vue内容,删减后保留如下内容:
<template> <div class="dashboard-editor-container"> <github-corner class="github-corner" /> <panel-group @handleSetLineChartData="handleSetLineChartData" /> <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> <line-chart :chart-data="lineChartData" /> </el-row> </div> </template> <script> import GithubCorner from '@/components/GithubCorner' import PanelGroup from './components/PanelGroup' import LineChart from './components/LineChart' const lineChartData = { ...... } export default { name: 'DashboardAdmin', components: { GithubCorner, PanelGroup, LineChart }, ...... } </script> <style lang="scss" scoped> ...... </style>在/src/views/newdashboard下建立components目录,拷贝vue-element-admin/src/views/admin/dashboard下的文件和文件夹: /src/views/dashboard/admin/components/LineChart.vue /src/views/dashboard/admin/components/PanelGroup.vue /src/views/dashboard/admin/components/minxins
注:解决方案见第5章。
启动服务webpack提示: [Vue warn]: Error in mounted hook: “TypeError: Object(…) is not a function” /src/views/newdashboard/components/LineChart.vue文件中 <script> import echarts from 'echarts' require('echarts/theme/macarons') // echarts theme import resize from './mixins/resize'"./mixins/resize"指向/src/views/newdashboard/components/mixins/resize.js文件,文件中:
import { debounce } from '@/utils'“@/utils”指向/src/utils/index.js文件,发现文件中没有“debounce”函数,需要从vue-element-admin工程中把代码拷贝移植过来。
[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components 出现这个错误的原因 检查一下你引入的组件里面是否在components里面写入子组件。 /src/views/opeff/outlet/components/TransactionTable.vue?vue&type=script&lang=js&) Module not found: Error: Can’t resolve ‘@/api/remote-search’ in ‘D:\VueApp\vue-admin-template-permission-control\src\views\opeff\outlet\components’ 把/src/api/remote-search.js文件移植拷贝到工程中。当在代码中引用ECharts、数字滚动等新增插件,需要在/package.json中注册插件,如下所示:
"dependencies": { "axios": "0.18.1", "core-js": "3.6.5", "echarts": "4.2.1", //新增 "element-ui": "2.13.2", "js-cookie": "2.2.0", "normalize.css": "7.0.0", "nprogress": "0.2.0", "path-to-regexp": "2.4.0", "vue": "2.6.10", "vue-count-to": "1.0.13", //新增 "vue-router": "3.0.6", "vuex": "3.1.0" },或者,手动安装echarts,npm install echarts --save。
注:在HBuilder X开发工具下,需要先删除目录/node_modules,并删除package-lock.json,修改package.json文件,增加“echarts”配置,重新npm install。
路由文件(/src/router/index.js)中的icom的描述与图标对应。
path: 'newdashboard', name: 'NewDashboard', component: () => import('@/views/newdashboard/index'), meta: { title: '首页', icon: 'dashboard' }运行vue-element-admin项目,“Icons”菜单下能看到已经集成到的图标,按名称引用和拷贝。
例如/src/views/newdashboard/components/PanelGroup.vue文件需要图标,如下图所示,需要把图标peoples.svg拷贝到/src/icons/svg目录下。
做后台项目区别于做其它的项目,权限验证与安全性是非常重要的,可以说是一个后台项目一开始就必须考虑和搭建的基础核心功能。我们所要做到的是:不同的权限对应着不同的路由,同时侧边栏也需根据不同的权限,异步生成。这里先简单说一下,我实现登录和权限验证的思路。[2]
登录:当用户填写完账号和密码后向服务端验证是否正确,验证通过之后,服务端会返回一个token,拿到token之后(我会将这个token存贮到cookie中,保证刷新页面后能记住用户登录状态),前端会根据token再去拉取一个 user_info 的接口来获取用户的详细信息(如用户权限,用户名等等信息)。权限验证:通过token获取用户对应的 role,动态根据用户的 role 算出其对应有权限的路由,通过 router.addRoutes 动态挂载这些路由。大多数系统都有根据用户权限,或者说角色,展示相应菜单/页面的需求,目录权限直接体现在/src/router/index中。
结合框架来实现目录的控制,如果是传统项目,一般是把目录结构整个存在后台数据库里,然后前端循环展示出来,但是这个在这里不需要这么麻烦,只需要把每个页面对应的权限保存起来就行了
/src/router/index表示目录为两个部分: constantRouterMap 与 asyncRouterMap
constantRouterMap:主要是通用部分,每个用户都有的页面asyncRouterMap:需要进行权限过滤的页面通过“/src/permission.js ”代码,按角色控制选择菜单。
通过参考/mock/user.js,可以明确知道系统角色定义为admin和editor,参考如下:
const tokens = { admin: { token: 'admin-token' }, editor: { token: 'editor-token' } } const users = { 'admin-token': { roles: ['admin'], introduction: 'I am a super administrator', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', name: 'Super Admin' }, 'editor-token': { roles: ['editor'], introduction: 'I am an editor', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', name: 'Normal Editor' } }本实践后台采用Python开发,使用基于Tornado的pyrestful插件开发rest服务。后续详见《vue-element-admin/template+tornado(pyrestful)前后端分离框架实践(2)——登录过程与后端python服务》。
由于笔者水平有限,时间仓促,欢迎讨论交流。
参考:
[1]《vue-element-admin》 [2]《手摸手,带你用vue撸后台 系列二(登录权限篇)》 掘金 , 花裤衩 ,2017年5月 [3]《vue-element-admin登录流程》 博客 , 兔子零84 , 2019年09月 [4]《Vue 新手学习笔记:vue-element-admin 之登陆及目录权限控制》 博客 ,乐之终曲 ,2019年05月 [5]《Access-Control-Allow- 设置 跨域资源共享 CORS 详解》 博客 ,Normal Developer , 2017年12月 [6]《Cross-Origin Resource Sharing (CORS》) MDN web docs [7]《使用vueAdmin开发后台管理系统(登录篇)》 博客 ,zw沐知 , 2020年7月 [8]《Nginx+Vue.js+Tornado前后端分离架构环境实践(2)》 博客 , 肖永威 2020年10月
