框架介绍
Element-UI是饿了么前端团队开源组件库,在国内受众比较多,贴合国人使用习惯
Element-Admin 是一个后端前端解决方案,基于Vue和Element-UI实现,内置了后台基本功能模块(多语言、路由、权限等),本项目是基于Elemnt-Admin上做的二次开发
安装
从码云下载脚手架代码
git clone https://gitee.com/django-extend/element-django.git my-project
cd my-project
cnpm install
npm run dev
入门
官方文档已经足够详细了,可以直接阅读,下面列出的是在官方框架上做的修改部分
目录结构
Django部分的目录结构 (src/components/Django)
.
├── api # 后端ajax请求封装
│ └── resource.js
├── components # element扩展
│ └── Table.vue # elx-table 扩展列表组件
├── fields # 字段列表
│ ├── DjangoField.vue # models.Field (所有字段)
│ ├── DjangoFileField.vue # models.FileField
│ ├── DjangoImageField.vue # models.ImageField
│ ├── DjangoManyToManyField.vue # models.ManyToManyField
│ ├── DjangoValue.vue # 值插槽,列表页和查看页使用
│ └── ForeignSelect.vue # models.ForeignKey
├── form # 表单列表
│ ├── ChangePasswordDialog.vue # 修改密码弹框
│ ├── ChangePasswordForm.vue # 修改密码表单
│ ├── DialogOrDrawer.vue # 弹框抽象(对话框/抽屉)
│ ├── EditDialog.vue # 新增页/编辑页
│ ├── EditForm.vue # 编辑表单
│ ├── ViewDialog.vue # 查看页
│ └── ViewForm.vue # 查看表单
├── index.vue # 列表页
└── models # 数据模型
└── meta.js # metainfo本地缓存
鉴权
// src/utils/request.js 行 22
config.headers['Authorization'] = 'Bearer ' + token
与后端约定在请求头里面加入 Authorization: Bearer ****
做为鉴权信息
动态菜单与路由
请求后端接口/api/auth/userinfo/
,会将用户的菜单信息回传给前端
{
"menus": [
{
"name": "dashboard",
"key": "dashboard",
"component": "dashboard",
"meta": {
"icon": "dashboard",
"title": "站点管理"
}
},
{
"name": "auth",
"key": "auth",
"component": "menu",
"meta": {
"icon": "table",
"title": "认证和授权"
},
"children": [
{
"name": "auth.group",
"key": "group",
"component": "django",
"meta": {
"title": "组",
"permission": "auth-group"
}
},
{
"name": "auth.user",
"key": "user",
"component": "django",
"meta": {
"title": "用户",
"permission": "auth-user"
}
}
]
}
]
}
其中的component比较重要,前端需要根据这个字符串去动态加载组件,组件库定义如下,可自行扩展
// src/utils/components.js
import Layout from '@/layout'
const components = {
defaults: {
'menu': Layout,
'dashboard': () => import('@/views/Dashboard'),
'django': () => import('@/components/Django')
},
custom: {
},
get(key) {
return this.custom[key] || this.defaults[key]
}
}
export default components
动态路由实现比较复杂,在源码中做了注释,可以搜索动态菜单步骤
来阅读整个链路源码了解原理
步骤 | 代码 |
---|---|
1.从后端读取菜单列表 | src/permission.js |
2.向vuex发起指令,通知生成菜单 | src/permission.js |
3.收到指令,调用步骤4函数生成路由 | src/store/modules/permission.js |
4.动态生成菜单 | src/store/modules/permission.js |
5.将路由写入本地存储 | src/store/modules/permission.js |
6.将动态路由写入vue-router | src/permission.js |
前端自定义菜单入口在src/router/index.js
export const asyncRoutes = [
]
可以在这里加入菜单,菜单的格式在该文件头部有注释,也可以看官方文档
注意,菜单中的roles已被废除掉
element扩展组件 elx-table
exl-table是对ex-table列表组件的扩展,增强了如下功能
- 集成了分页
- 数据源参数data修改为function(原参是array),这样才能集成分页
- 增加了多选功能,分页切换能保持选中
由于集成了服务端分页,对服务端返回结果做了如下数据结构约定
{
"pageSize": 20, // 一页显示多少记录
"pageNo": 1, // 当前第几页
"totalPage": 5, // 总页数
"totalCount": 100, // 总记录数
"data": [] // 当页记录集
}
- 扩展参数说明
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
data | 数据源 | function | - |
row-key | 主键名 | string | - |
page-size | 分页页数 | number | 10 |
row-selection | 列表项是否可选择 | object | null |
- 范例
<template>
<div class="app-container">
<ext-table
row-key="key"
:data="loadData"
:page-size="20"
:row-selection="{selectedRowKeys: selectedRowKeys, onChange: handleSelectChange}"
>
<el-table-column prop="key" label="ID" />
<el-table-column prop="name" label="名称" />
</ext-table>
</div>
</template>
<script>
import ExtTable from '@/components/Django/components/Table.vue'
export default {
components: { ExtTable },
data() {
return {
selectedRowKeys: []
}
},
methods: {
loadData(params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = []
const pageSize = params.pageSize || 10
const pageNo = params.pageNo || 1
const maxCount = 150
for (let i = 0; i < pageSize; i++) {
const key = (pageNo - 1) * pageSize + i + 1
if (key > maxCount) {
break
}
const item = {
key: key,
name: `Item${key}`
}
data.push(item)
}
const result = {
pageSize: pageSize,
pageNo: pageNo,
totalPage: Math.ceil(maxCount / pageSize),
totalCount: maxCount,
data: data
}
resolve(result)
}, 1000)
})
},
handleSelectChange(keys) {
this.selectedRowKeys = keys
console.log('select keys:', keys)
}
}
}
</script>