tablex 是一个基于 Vue 、ELement UI 、 Axios 实现的一个 table 组件,可根据配置快速实现增删改查业务
npm i @~crazy/tablex -S
- main.js
// 引入
import tablex from '@~crazy/tablex'
// 安装
Vue.use(tablex, {
// 全局配置
});
// 全局访问 tablex 对象
Vue.$tablex;
属性名 | 说明 |
---|---|
version | 版本号 |
api | 接口对象,根据 request.map 配置生成的接口函数 |
responseFormat | 全局请求响应数据格式化回调 |
options | 配置 |
type | 类型对象 |
配置名 | 类型 | 默认值 | 说明 |
---|---|---|---|
i18n | Object | - | Vue I18n 实例,实现组件国际化 |
locales | Object | - | 国际化语言列表 |
store | Obejct | - | Vue Store 实例 |
request | Object | - | 请求配置 |
request.map | Object | - | 接口地图 |
request.axios | Object | - | Axios 配置 |
request.axios.authorizationKey | String | Authorization | 在请求头携带的 Token 认证名称 |
request.axios.defaults | Object | - | 同 Axios 配置 |
request.axios.defaults.timeout | Number | 1000 * 5 | 请求超时毫秒数 |
request.axios.defaults.withCredentials | Boolean | true | 跨域请求是否需要使用凭证 |
request.axios.defaults.headers | Object | { 'Content-Type': 'application/json;charset=UTF-8' } |
请求头配置 |
request.axios.interceptors | Object | - | 自定义拦截处理回调 |
request.axios.interceptors.request | Array[Function] | [] | 请求处理回调列表 |
request.axios.interceptors.response | Array[Function] | [] | 响应处理回调列表 |
table | Object | - | Table 组件配置 |
table.requestFormat | Function | - | 全局请求参数格式化回调 |
table.responseFormat | Function | - | 全局响应数据格式化回调 |
table.deleteRequestFormat | Function | - | 全局删除请求参数格式化回调 |
table.delete | Obejct | - | 删除行动配置 |
table.delete.key | String | id | 发送请求时参数的名称 |
table.delete.paramKey | String | id | 获取参数时数据列的名称 |
table.paging | Obejct | - | 分页配置 |
table.paging.paramsFormat | Function | - | 分页参数格式化回调 |
Vue.use(tablex, {
// Vue I18n
i18n: null,
// 国际化语言列表
locales: {},
// Vue Store
store: null,
// 请求配置
request: {
// 接口地图
map: {},
// axios 配置
axios: {
authorizationKey: 'Authorization',
// 全局配置
defaults: {
// 请求超时毫秒数
timeout: 1000 * 5,
// 跨域请求是否需要使用凭证
withCredentials: true,
// 请求头配置
headers: {
'Content-Type': 'application/json;charset=UTF-8',
},
},
// 自定义拦截处理回调
interceptors: {
request: [],
response: [],
},
},
},
table: {
// 全局请求参数格式化回调
requestFormat: null,
// 全局响应数据格式化回调
responseFormat: null,
// 全局删除请求参数格式化回调
deleteRequestFormat: null,
// 删除
delete: {
// 参数键
key: 'id',
// 获取参数值的键
paramKey: 'id',
},
// 分页
paging: {
// 分页参数格式化回调
paramsFormat: null,
},
},
})
格式为 JSON,接口集合可多层嵌套
- 格式
{
接口名称:'请求方式,GET / POST',
// 如 POST : http://XXXX/login
login: 'post',
自定义接口函数名称: ['请求方式,GET / POST', '接口名称'],
// 如 POST :http://XXXX/login
// 自定义接口函数名为 Login
Login: ['post', 'login'],
接口集合名(以开头的名称命名):{},
// 如有以下以 system 开头的接口:
// POST:http://XXXX/system/setUser
// GET:http://XXXX/system/getUserData
system: {
setUser: 'post',
getUserData: 'get',
},
接口集合名(不以开头的名称命名):{},
// 如有以下以 system 开头的接口:
// POST:http://XXXX/system/setUser
// GET:http://XXXX/system/getUserData
SystemData: {
// 设置默认接口前缀
default: 'system',
setUser: 'post',
getUserData: 'get',
},
}
- 示例
import tablex from '@~crazy/tablex';
// 配置
Vue.use(tablex, {
request: {
map: {
// 设置用户数据
setUserData: ['post', 'set_user_data'],
},
},
});
// 通过 api 属性访问
// 获取请求实例
const req = this.$tablex.api.setUserData({
// 传递参数
nickname: 'admin',
address: 'xxxxxx',
});
// 发送请求
req.send({
// 此处可覆盖参数
}).then(res => {
// 请求成功
});
// 取消请求
req.cancel();
为了实现各种数据类型在界面上的展示(Visible)、编辑(Edit),在此定义了几种数据类型(文档中为了不与原生属性混淆,使用 tablex 作为前缀):
基类,所有类型均继承此类。目前有以下类:
类型 | 继承于 | 说明 |
---|---|---|
tablex.String | tablex.Type | 字符串 |
tablex.JSON | tablex.Type | json 对象,尚未实现 |
tablex.Double | tablex.Type | 浮点数 |
tablex.Password | tablex.String | 密码 |
tablex.Date | tablex.Type | 日期,YYYY-MM-DD HH:mm:ss |
tablex.Time | tablex.Date | 时间点,HH:mm:ss |
tablex.DateRange | tablex.Type | 时间区间,YYYY-MM-DD HH:mm:ss - YYYY-MM-DD HH:mm:ss |
tablex.Select | tablex.Type | 下拉选择器 |
tablex.Radio | tablex.Select | 单选 |
tablex.Checkbox | tablex.Radio | 多选 |
不同类型函数传参有所不同
- constructor 构造函数 & set
参数 | 类型 | 默认值 | 适用类型 | 参数顺序 | 说明 |
---|---|---|---|---|---|
value | Any | - | 所有 | - | 原始数据值,不同类型会根据 value 作出不同的显示方式 |
formatString | String | YYYY-MM-DD HH:mm:ss | tablex.Date | (value, formatString) | 格式化显示方式,不包含 Edit 状态 |
HH:mm:ss | tablex.Time | ||||
YYYY-MM-DD HH:mm:ss | DateRange | (start, end, formatString) | |||
start | String/Number/Date | - | tablex.DateRange | (start, end, formatString) | 开始时间 |
end | String/Number/Date | - | tablex.DateRange | (start, end, formatString) | 结束时间 |
options | Array[Object({ lable: String, value: String, })] |
[] | tablex.Select | (value, options) | 数据列表 |
tablex.Radio | |||||
tablex.Checkbox |
- getEditor
获取类型编辑器,编辑器可修改数据值返回到数据源中。多用于表单提交新增、修改功能
参数 | 类型 | 默认值 | 适用类型 | 参数顺序 | 说明 |
---|---|---|---|---|---|
vue | Vue | - | 所有 | - | Vue 实例对象 |
props | Object | - | tablex.String | (vue, props) | 同 el-input 组件参数 |
tablex.Password | |||||
tablex.Double | 同 el-input-number 组件参数 | ||||
tablex.Date | 同 el-date-picker 组件参数 | ||||
tablex.DateRange | |||||
tablex.Time | 同 el-time-picker 组件参数 | ||||
tablex.Select | 同 el-select 组件参数 | ||||
tablex.Radio | 同 el-radio 组件参数 | ||||
tablex.Checkbox | 同 el-checkbox 组件参数 |
- toVisible
将原始数据转换为显示状态
参数 | 类型 | 默认值 | 适用类型 | 参数顺序 | 说明 |
---|---|---|---|---|---|
vue | Vue | - | 所有 | - | Vue 实例对象 |
placeholder | String | - | tablex.String | (vue, placeholder) | 占位文本 |
tablex.Password | |||||
precision | Number | 0 | tablex.Double | - | 精度 |
formatString | String | - | tablex.Date | (vue, formatString) | 格式化显示方式,为空时使用实例的 formatString 值 |
tablex.Time | |||||
tablex.DateRange |
- toJson
将原始数据转换为 JSON 对象
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
key | String | - | 原始值的键 |
keyAlias | String/Array[String] | - | 需要将原始值转化的别名键 |
value | Any | - | 原始值 |
配置名 | 类型 | 说明 |
---|---|---|
options | Object | tablex 组件配置,tablex 依靠此配置工作 |
tablex | tablex 实例 | 父级 tablex 实例,在多个 tablex 嵌套使用插槽时传入 |
- 示例
<template>
<!-- 引用 -->
<el-tablex :options="options"></el-tablex>
</template>
<script>
export default {
computed: {
options: {
// tablex 组件配置
},
},
};
</script>
- 多个 tablex 嵌套
<template>
<!-- 引用 -->
<el-tablex :options="options">
<!-- 嵌套的 tablex 使用插槽,options 与 tablex 属性需要使用作用域变量传入 -->
<el-tablex slot="table-details" slot-scope="scope" :options="scope.options" :tablex="scope.tablex"></el-tablex>
</el-tablex>
</template>
<script>
export default {
computed: {
options: {
// 省略部分代码...
actions: {
// 查看详情列表
details: {
table: {
// 此处为嵌套 tablex
},
},
},
},
},
};
</script>
配置名 | 类型 | 默认值 | 说明 |
---|---|---|---|
multiple | Boolean | false | 开启列表多选功能 |
model | Object(tablex.Model) | - | 数据模型 |
data | Array | null | 列表数据 |
actions | Object(tablex.Action) | - | 行为列表 |
actionParams | Object | - | 全局行为请求时附带参数 |
requestFormat | Function | null | 全局请求参数格式化回调 |
responseFormat | Function | null | 全局响应数据格式化回调 |
deleteRequestFormat | Function | null | 全局删除请求参数格式化回调 |
condition | Object | - | 查询条件 |
condition.showButton | Boolean | true | 显示查询按钮 |
condition.updateOnChange | Boolean | false | 查询条件改变立即更新 |
condition.toUrl | Boolean | true | 将条件参数附加到浏览器 url |
condition.list | Array[tablex.Model] | [] | 查询列表 |
operation | Object | - | 列表操作 |
operation.title | String | null | 操作栏显示的标题文本 |
operation.width | String | null | 操作栏的宽度,需要带 px 或 % |
operation.toExpand | Boolean | true | 当存在展开行时将操作加入到行内 |
operation.list | Array[tablex.Operation] | [] | 操作列表 |
paging | Object | - | 分页 |
paging.visible | Boolean | true | 显示分页 |
paging.describe | Boolean | true | 显示描述 |
paging.toUrl | Boolean | true | 将分页参数附加到浏览器 url |
paging.paramsFormat | Function | null | 分页参数格式化回调 |
props | Object | - | 额外参数 |
props.table | Object | - | 同 el-table 组件参数 |
props.table.stripe | Boolean | true | 是否为斑马纹 table |
props.pagination | Object | - | 同 el-pagination 组件参数 |
props.pagination.background | Boolean | true | 是否为分页按钮添加背景色 |
props.pagination.small | Boolean | true | 是否使用小型分页样式 |
props.pagination.pageSize | Number | 10 | 每页显示条目个数 |
props.pagination.currentPage | Number | 1 | 当前页数 |
props.pagination.pageSizes | Array[Number] | [5, 10, 20, 30, 40, 50, 100] | 每页显示个数选择器的选项设置 |
目前 model 、 condition.list 这两个组件配置项使用此模型配置,其中 model又分为 Visible(展示) 模式 与 Edit(编辑) 模式,但不是所有配置都适用。为方便阅读理解,在下面列表的适用配置项会用 model 、 condition 表示:
配置名 | 类型 | 默认值 | 适用配置项 | 适用 model 模式 | 说明 |
---|---|---|---|---|---|
type | String | tablex.String | 所有 | 所有 | 对应 tablex 数据类型 此处额外多两个类型: $index:返回行号 expand:展开行,同 el-table 展开行功能,只适用于 Visible 模式。注意:一个数据模型里最多只能存在一个 expand |
key | String | - | condition | - | 数据键 |
keyAlias | String/Array[String] | null | 所有 | 所有 | 数据键别名 |
data | Array[Any] | - | 所有 | 所有 | 数据来源,等同于 tablex.type 构造函数的传参, 从第二位开始 |
label | String | - | 所有 | 所有 | 组件显示的标签 |
slots | Function | null | 所有 | 所有 | 插槽自定义函数 |
format | Function | null | 所有 | 所有 | 格式化数据回调 |
props | Object | - | 所有 | 所有 | 同对应的数据类型所对应的 element-ui 组件配置以及 el-table-column 配置 |
props.value | Any | - | 所有 | 所有 | 数据值,可与 editOpts.watch 配合使用 |
visible | Boolean | true | 所有 | Visible | 是否显示 |
model | Object(tablex.Model) | null | model | Visible | 在 type 为 expand 时适用,格式同 tablex 组件配置的 model |
editOpts | Object | - | 所有 | Edit | 编辑/输入时的选项 |
editOpts.vibible | Boolean | true | 所有 | Edit | 是否显示 |
editOpts.readonly | Boolean | false | 所有 | Edit | 是否只读 |
editOpts.watch | Function | null | 所有 | Edit | 值监听回调函数 |
updateOnChange | Boolean | false | condition | - | 此查询条件值改变后立即请求更新 |
- 示例
<template>
<el-tablex :options="options"></el-tablex>
</template>
<script>
export default {
computed: {
options(){
return {
// model 示例
model: {
// 使用 type 为 $index 显示行号
$index: {
type: '$index',
},
// 此处 name 对应 配置里的 key
name: {
// type 默认为 tablex.String,
type: 'String',
label: '姓名',
},
sex: {
type: 'Radio',
label: '性别',
// 由于性别需要单选,这里传入数据来源
data: [
// 第一个参数,性别列表,对应 tablex.Raido 构造函数的 options 参数
[{
label: '男',
// 注意此处 value 值必须为 String 类型
value: '0',
}, {
label: '女',
value: '1',
}],
],
},
// 使用展开行,因为 expand 在一个数据模型里最多只能存在一个,所以可以直接使用 key 作为 type 类型
expand: {
model: {
age: {
label: '年龄',
},
address: {
label: '地址',
props: {
// 使用多行文本框
type: 'textarea',
},
},
},
},
},
// condition 查询条件示例
condition: {
list: [{
key: 'name',
label: '姓名',
}],
},
};
},
},
};
</script>
配置名 | 类型 | 默认值 | 说明 |
---|---|---|---|
key | String | - | 操作唯一的键,可以通过 operation-${key} 使用插槽 |
label | String | - | 操作显示的文本内容,使用插槽时无效 |
trigger | Function | - | 点击时触发的回调。使用插槽时无效,需自定义交互 |
visible | Boolean/Function | true | 是否显示此操作,回调中可获取到当前数据用于逻辑判断 |
- 示例
<template>
<el-tablex :options="options">
<!-- 使用插槽 -->
<el-button slot="operation-delete" slot-scope="scope" @click="deleteRow(scope)" type="danger" icon="el-icon-delete-solid" circle></el-button>
</el-tablex>
</template>
<script>
export default {
computed: {
options() {
return {
operation: {
list: [{
key: 'edit',
label: '修改',
trigger: scope => {
// 通过 scope.row 可以获取当前操作的数据
},
}, {
// 使用插槽
key: 'delete',
}],
},
};
},
},
methods: {
deleteRow(scope) {
// 通过 scope.row 可以获取当前操作的数据
},
},
};
</script>
tablex 所有的交互都是围绕 action 开展的,通过 action 驱动增删改查及各种操作
tablex 内置了四种常用的 action :
- select (查询)select 是 tablex 表格的数据来源
- insert (新增)
- edit (修改)
- delete (删除)
配置名 | 类型 | 默认值 | 说明 |
---|---|---|---|
method | String/Function | - | 此行为调用的服务端接口或自定义回调函数 |
params | Object | null | 调用时附带的参数 |
before | Function | - | 调用前请求参数格式化回调 |
after | Function | - | 调用后响应数据格式化回调 |
editor | Object | - | 表单弹窗配置 |
editor.customClass | String | - | 自定义弹窗类名 |
editor.title | String | - | 弹窗标题 |
editor.width | String | - | 弹窗宽度,px 或 % |
editor.props | Object | - | 弹窗组件配置,同 el-dialog |
editor.labelWidth | String | - | 表单标签宽度,px 或 % |
editor.model | Object(tablex.Model) | - | 表单数据模型 |
editor.sendParams | Array[String] | - | 定义发送参数列表 |
table | Object | - | 表格弹窗配置 |
table.customClass | String | - | 自定义弹窗类名 |
table.title | String | - | 弹窗标题 |
table.width | String | - | 弹窗宽度,px 或 % |
table.props | Object | - | 弹窗组件配置,同 el-dialog |
table.options | Object(tablex.Options) | - | tablex 配置选项 |
table.on | Object | - | 事件绑定 |
- 示例
<template>
<el-tablex :options="options"></el-tablex>
</template>
<script>
import axios from 'axios';
export default {
computed: {
options() {
return {
operation: {
list: [{
// 更新状态操作按钮
key: 'status',
trigger: scope => scope.action('updateStatus', scope, {
id: scope.row.id,
}),
}, {
// 查看详情列表操作按钮
key: 'details',
trigger: scope => scope.action('getDetails', scope, {
id: scope.row.id,
}),
}],
},
actions: {
// 查询数据
select: {
// 此接口为注册 tablex 时由全局配置 request.map 传入
method: 'getData',
},
// 自定义 action
// 更新状态
updateStatus: {
// 使用自定义回调
method: async (params, scope) => {
// 自定义请求
const res = await axios.post('http://XXXX/updateStatus', {
params,
});
// 响应数据必须返回
return res;
},
},
// 查看详情列表
getDetails: {
// 使用表格展示
table: {
options: {
actions: {
select: {
method: 'getDetails',
},
},
},
},
},
},
};
},
},
};
</script>
事件名 | 说明 | 参数 | 参数说明 |
---|---|---|---|
action | 当 tablex 有 action 执行时触发 | name | 行为名称 |
close | 当前组件窗口被销毁 | tablex | 当前 tablex |
name | 行为名称 | ||
params | 多个参数,根据实际情况获取 | ||
condition-close | 条件查询被关闭时触发 | - | - |
selection-change | 当前表格选择的数据发生变化 | value | 当前选择数据集合 |
插槽名 | 说明 |
default | 拓展操作栏内容 |
insert | 自定义新增操作按钮内容 |
delete | 自定义多选删除操作按钮内容 |
column-${key} | 自定义表格列的内容 |
operation-${key} | 自定义表格操作列的内容 |
form-${key} | 自定义弹窗表单项内容,多个弹窗时存在相同 key 的项可以使用 actionName 区分 |
${actionName}-from-${key} | |
${actionName}-dialog-footer | 拓展弹窗底部内容 |
${actionName}-dialog-footer-cancel | 自定义弹窗底部取消按钮内容 |
${actionName}-dialog-footer-confirm | 自定义弹窗底部确认按钮内容 |
table-${actionName} | 自定义弹窗的嵌套 tablex 内容 |
- main.js
import 'babel-polyfill';
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import VueI18n from 'vue-i18n';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import tablex from '@~crazy/tablex';
Vue.use(VueI18n);
Vue.use(ElementUI, {
size: 'mini',
});
const i18n = new VueI18n({
locale: 'zh-cn',
silentTranslationWarn: true,
messages: {
'zh-cn': {},
en: {},
},
});
Vue.use(tablex, {
i18n,
request: {
map: {
getApiList: 'get',
getApiData: 'get',
},
axios: {
defaults: {
baseURL: 'https://crazy-gt.com/crazy-api/',
},
},
},
table: {
responseFormat: res => {
return {
...res,
total: res.total || res.data.length,
};
},
},
});
Vue.config.productionTip = false
new Vue({
router,
store,
i18n,
render: h => h(App)
}).$mount('#app')
- app.vue
<template>
<el-tablex :options="options">
<!-- 自定义数据源内容 -->
<el-tag v-if="scope.row.data_source" slot="column-data_source" slot-scope="scope">{{scope.row.data_source}}</el-tag>
<!-- 自定义是否为列表内容 -->
<el-tag slot="column-is_list" slot-scope="scope" :type="scope.row.is_list ? 'success' : 'danger'">{{scope.row.is_list}}</el-tag>
<!-- 自定义嵌套 tablex 内容 -->
<el-tablex slot="table-details" slot-scope="scope" :options="scope.options" :tablex="scope.tablex">
<div slot="column-content" slot-scope="scope" class="column-content">{{scope.row.content}}</div>
</el-tablex>
<el-tablex slot="table-list" slot-scope="scope" :options="scope.options" :tablex="scope.tablex">
<!-- 自定义数据源内容 -->
<el-tag v-if="scope.row.data_source" slot="column-data_source" slot-scope="scope">{{scope.row.data_source}}</el-tag>
<!-- 自定义是否为列表内容 -->
<el-tag slot="column-is_list" slot-scope="scope" :type="scope.row.is_list ? 'success' : 'danger'">{{scope.row.is_list}}</el-tag>
</el-tablex>
</el-tablex>
</template>
<script>
export default {
computed: {
model() {
return {
id: {},
no: {
label: '编号',
},
name: {
label: '名称',
},
data_source: {
label: '数据源',
},
is_list: {
type: 'Radio',
label: '是否为列表',
data: [
[{
label: '否',
value: false,
}, {
label: '是',
value: true,
}],
],
},
};
},
options() {
return {
multiple: true,
model: this.model,
operation: {
list: [{
key: 'details',
label: '查看详情',
trigger: scope => scope._self.action('details', scope, scope.row),
visible: scope => !scope.row.is_list,
}, {
key: 'list',
label: '列表详情',
trigger: scope => scope._self.action('list', scope, scope.row),
visible: scope => scope.row.is_list,
}],
},
actions: {
select: {
// 使用回调函数自定义数据
method: async ({
page,
size,
}) => {
const {
data,
} = await this.$tablex.api.getApiList().send();
return {
data: [...data].splice((page - 1) * size, size),
total: data.length,
};
},
},
list: {
table: {
title: '列表详情',
options: {
model: this.model,
actions: {
select: {
method: params => ({
data: params.list,
}),
},
},
paging: {
visible: false,
},
},
},
},
details: {
// 嵌套的 tablex
table: {
title: '查看详情',
options: {
model: {
no: {
label: '编号',
},
type: {
label: '类型',
},
content: {
label: '数据内容',
},
},
actions: {
select: {
method: 'getApiData',
sendParams: ['id'],
},
},
paging: {
visible: false,
},
},
},
},
},
};
},
},
}
</script>
<style lang="scss">
.column-content {
background: #333;
color: #FFF;
padding: 10px;
border-radius: 4px;
}
</style>