# 介绍
agel-table (opens new window)是 element-ui table 的二次封装,保持灵活性,极简的思想,更少的代码,更多的功能,更快速的开发 ⬆⬆⬆
(opens new window)
(opens new window)
# 特性
该组件的思想就是以一个 table 对象来做所有的操作,哪怕页上多个列表也不用在 data 定义一堆 data1,data2,loading1,loading2 ... 等变量,更加简单明了,适用于 vue2+elementUI。
- 保持灵活性,极简的思想,更少的代码,更多的功能,更快速的开发
- 支持 element-ui table 组件的所有 api, slot, event, method
- 纯数据配置
- 集成分页组件
- 菜单列
- 动态显隐列
- 数据代理
- 自动合并相同行
- 虚拟滚动支持大数据渲染 10w+
- 跟随容器大小自适应高度
# 安装
npm install agel-table --save # yarn add agel-table
# 创建表格
# 接口代理
这是一个基础的查询表格例子,表格通过一个 table 对象渲染,组件渲染完成之后会注入默认方法和属性到 table 中,方便你通过 table 直接进行所有操作。
表格
page
对象用于配置 Pagination 分页组件的属性,当分页变化会自动同步修改。【可全局配置】表格
menu
对象用于配置 菜单列,进行编辑删除等,按需使用。【可全局配置】设置
request
开启接口代理,使用table.getData
进行主动触发,当分页排序变化时自动触发。表格
query
对象默认存在四个查询属性,分别为currentPage pageSize orderColumn order
,当分页排序发生变化时对会自动同步对应数据到 query 对象中。
点击查看代码
<template>
<div class="demo">
<p><code v-show="queryString">{{queryString}}</code></p>
<p>
<el-input v-model="table.query.name" style="width:100px;margin-right:10px;"></el-input>
<el-button icon="el-icon-search" @click="()=>table.getData({ currentPage: 1 })">查询</el-button>
</p>
<agel-table v-model="table"></agel-table>
</div>
</template>
<script>
export default {
data() {
return {
table: {
border: true,
data: [],
height:300,
// 该对象放置table 对象的查询参数,默认有 currentPage,pageSize,orderColumn,order
query: { name: "小虎" },
// 默认排序列
defaultSort: { prop: "date", order: "descending" },
// 分页组件在此配置,建议配置在全局,页面可省略
page: {
enable: true,
currentPage: 1,
pageSize: 5,
pageSizes: [5, 10, 15, 20],
},
// 菜单列配置
menu: {
enable: true,
fixed: "right",
onEdit: ({ row }) => {
this.$message.info("编辑", row.date);
},
onDel: ({ row }) => {
this.$message.info("删除", row.date);
},
},
// 表格列配置
columns: [
{ label: "日期", prop: "date", width: 200, sortable: "custom" },
{ label: "姓名", prop: "name", width: 200 },
{ label: "地址", prop: "address", minWidth: 300 },
],
// 接口函数
request: (query, done, err) => {
// query == this.table.query
this.getHttpData(query)
.then((res) => done({ data: res.data, total: res.total }))
.catch(err);
},
},
};
},
computed: {
queryString() {
return JSON.stringify(this.table.query);
},
},
// table.getData 只能在 mounted 生命周期之后调用
mounted() {
this.table.getData();
},
methods: {
getHttpData(query) {
// 模拟一个 http 请求
return new Promise((reslove) => {
setTimeout(() => {
let data = [];
for (let i = 0; i < query.pageSize; i++) {
let index = (query.currentPage - 1) * query.pageSize + (i + 1);
data.push({
date: "2016-05-02",
name: "王小虎" + index,
address: "上海市" + index,
});
}
reslove({ data: data, total: 100 });
}, 1000);
});
},
},
};
</script>
# 数据配置
这是一个复杂的例子,下面的 Demo 展示了 element-ui 官网 el-table 的大多数例子:
点击查看代码
<template>
<div class="demo">
<div style="margin-bottom:10px">
<el-button @click="clearSelection">清空选中</el-button>
<el-button @click="updateLabel">修改列信息</el-button>
</div>
<agel-table v-model="table"> </agel-table>
</div>
</template>
<script>
export default {
data() {
let data = [];
for (let i = 0; i < 10; i++) {
data.push({
date: "2016-05-01 10:20",
name: "王小虎" + i,
sex: i % 2 == 0 ? "男" : "女",
address: "上海市",
hasChildren: i == 0,
});
}
return {
table: {
data,
border: true,
stripe: true,
height: 400,
lazy: true,
highlightCurrentRow: true,
defaultSort: { prop: "name", order: "ascending" },
rowKey: "name",
treeProps: { children: "children", hasChildren: "hasChildren" },
showSummary: true,
summaryMethod: () => ["这", "是", "一", "个", "合", "计"],
rowClassName: ({ rowIndex }) => (rowIndex == 0 ? "success-row" : ""),
load: (tree, treeNode, resolve) => {
setTimeout(() => {
resolve([
{
date: "2016-05-01 10:20",
name: "王小虎",
sex: "男",
address: "上海市普陀区金沙江路 1517 弄",
},
]);
}, 1000);
},
columns: [
{
type: "selection",
width: 50,
align: "center",
fixed: true,
},
{
label: "#",
type: "index",
align: "center",
width: 50,
index: (index) => "#" + (index + 1),
},
{ label: "日期", prop: "date", width: 200 },
{
label: "配送信息",
children: [
{
label: "姓名",
prop: "name",
width: 80,
sortable: true,
},
{
label: "性别",
prop: "sex",
width: 80,
filters: [
{ text: "男", value: "男" },
{ text: "女", value: "女" },
],
filterMethod: (value, row) => row.sex === value,
},
{
label: "地址",
minWidth: 300,
prop: "address",
},
],
},
],
on: {
"selection-change": () => {
this.$message.success("选择项发生变化");
},
},
},
};
},
methods: {
clearSelection() {
this.table.getRef().clearSelection();
},
updateLabel() {
this.table.getCol("address").label = "地址" + Math.random();
},
},
};
</script>
<style>
.el-table .success-row {
background: #f0f9eb;
}
</style>
# 自定义列
设置 column.slotColumn
支持配置自定义列,支持渲染函数
设置 column.slotHeader
支持配置自定义表头,支持渲染函数
点击查看代码
<template>
<agel-table v-model="table">
<template v-slot:dateHeader>
<el-tag>模板自定义列-表头</el-tag>
</template>
<template v-slot:date="props">
<el-input v-model="props.row.date"></el-input>
</template>
<template v-slot:expand="props">
<div style="text-align:center">{{props.row.date}}=>template展开行内容</div>
</template>
<template v-slot:append>
<p slot="append" style="text-align:center">最后一行 slot append...</p>
</template>
</agel-table>
</template>
<script>
export default {
data() {
return {
table: {
border: true,
columns: [
{
label: "展开行",
type: "expand",
width: 80,
slotColumn: "expand",
},
{
minWidth: 200,
slotColumn: (h, { row }) => {
return <el-tag>{row.name}</el-tag>;
},
slotHeader: () => {
return <el-tag>render函数自定义列-表头</el-tag>;
},
},
{
minWidth: 200,
slotColumn: "date",
slotHeader: "dateHeader",
},
],
data: [
{ date: "2016-05-02", name: "王小虎", address: "上海市" },
{ date: "2016-05-04", name: "王小虎", address: "上海市" },
],
},
};
},
};
</script>
# 动态显隐
设置 column.display
控制是否显示隐藏,支持函数配置
点击查看代码
<template>
<div class="demo">
<div style="margin-bottom:10px">
<el-checkbox v-for="item in table.columns" v-if="item.prop" :key="item.prop" v-model="item.display">{{item.label}}</el-checkbox>
</div>
<agel-table v-model="table"></agel-table>
</div>
</template>
<script>
export default {
data() {
return {
address: true,
table: {
columns: [
{
type: "selection",
display: () => {
return this.table.columns[1].display;
},
},
{ label: "日期", prop: "date", width: 200, display: true },
{
label: "姓名",
prop: "name",
width: 200,
display: true,
},
{
label: "地址",
prop: "address",
minWidth: 300,
display: true,
},
],
data: [],
},
};
},
};
</script>
# 自动合并
设置 merge
可开启自动合并单元格。
点击查看代码
<template>
<div>
<p>设置 <code>merge.auto</code> 将自动纵向合并相同行</p>
<agel-table v-model="table"></agel-table>
<p>也可设置指定某一列 <code>columnb.merge</code> 进行合并 </p>
<agel-table v-model="table2"></agel-table>
<p>也可设置合并方向,<code>merge.direction</code>为<code>horizontal</code>横向合并相同列</p>
<agel-table v-model="table3"></agel-table>
</div>
</template>
<script>
export default {
data() {
const data = [
{ date: "2016-05-02", name: "王小虎", address: "上海市1" },
{ date: "2016-05-02", name: "王小虎", address: "上海市2" },
{ date: "2016-05-02", name: "王小虎", address: "上海市3" },
];
return {
table: {
border: true,
merge: { enable: true, auto: true },
columns: [
{ label: "日期", prop: "date", width: 200 },
{ label: "姓名", prop: "name", width: 200 },
{ label: "地址", prop: "address", minWidth: 300 },
],
data,
},
table2: {
border: true,
merge: { enable: true },
columns: [
{ label: "日期", prop: "date", width: 200, merge: true },
{ label: "姓名", prop: "name", width: 200 },
{ label: "地址", prop: "address", minWidth: 300 },
],
data,
},
table3: {
border: true,
merge: { enable: true, auto: true, direction: "horizontal" },
columns: [
{ label: "日期1", prop: "date1", width: 200 },
{ label: "日期2", prop: "date2", width: 200 },
{ label: "地址", prop: "address", minWidth: 300 },
],
data: [
{ date1: "2016-05-02", date2: "2016-05-02", address: "上海市1" },
{ date1: "2016-05-02", date2: "2016-05-02", address: "上海市2" },
{ date1: "2016-05-02", date2: "2016-05-03", address: "上海市2" },
],
},
};
},
};
</script>
# 虚拟滚动
设置 virtual
可开启虚拟滚动,纯文本渲染效率最佳 😄
只需要设置好 rowHieght
,表格会自动设置固定行高,不会被 CSS 样式表所影响。
支持多选列,索引列,固定列,排序,在组件内部做了兼容,不支持过滤、树形、合并单元格。
点击查看代码
<template>
<div class="demo">
<el-row style="margin-bottom:10px">
<el-input-number v-model="number" :min="1" :max="100000" :step="100" placeholder="数据条数"></el-input-number>
<el-button @click="setData">加载大数据</el-button>
<el-input-number v-model="rowIndex" :min="1" :max="table.data.length" placeholder="指定跳转行数"></el-input-number>
<el-button @click="jump">跳转到指定行数</el-button>
</el-row>
<agel-table v-model="table"></agel-table>
</div>
</template>
<script>
export default {
data() {
return {
number: 1000,
rowIndex: 100,
table: {
border: true,
height: 200,
virtual: { enable: true, rowHeight: 35 },
columns: [
{
type: "selection",
width: 60,
align: "center",
selectable: (row, index) => {
// console.log(index)
return index > 2;
},
},
{ label: "#", type: "index", width: 50, align: "center" },
{ label: "姓名", prop: "name", width: 200 },
{ label: "随机数", prop: "address", minWidth: 100, sortable: true },
],
data: [],
},
};
},
mounted() {
this.setData();
},
methods: {
setData() {
let data = [];
for (let i = 0; i < this.number; i++) {
// 冻结对象可获得更好的性能
data.push({
name: "王小虎" + (i + 1) + "号",
address: Math.random() * 100,
});
}
this.table.data = data;
},
jump() {
console.log(this.table.data[this.rowIndex])
this.table.virtualScrollToRow(this.table.data[this.rowIndex]);
},
},
};
</script>
# 自适应高
设置 resize
属性可开启自适应高度,请指定 relative
参照物,否则默认取的 table.offsetParent
点击查看代码
<template>
<div class="box border" style="margin-top:0px;height: 80vh;padding: 0px 20px">
<div class="head border" style="padding:20px 0px">
<el-input placeholder="姓名" style="width:100px"></el-input>
</div>
<agel-table class="body" v-model="table"></agel-table>
<div class="foot border" style="padding:20px 0px">table 底部容器</div>
</div>
</template>
<script>
export default {
data() {
return {
table: {
resize: {
enable: true,
relative: ".box",
offset: () => {
return document.querySelector(".foot").offsetHeight;
},
},
columns: [
{ label: "改变浏览器高度,table 会自适应容器高度", minWidth: 300 },
],
data: [],
},
};
},
};
</script>
<style>
.border {
box-sizing: border-box;
border: 1px solid #409EFF;
}
</style>
# 全局配置
- 所有属性均可全局配置,配置将被继承到每个表格上;
- 强烈建议分页与菜单列相关的属性建议配置在全局,在局部页面根据需求进行覆盖。
import agelTable from "agel-table"
const tableConfig = {
table: {
border: true,
highlightCurrentRow: true,
},
column:{
width:100,
},
menu:{
width:100,
editRender: ({ h, clickEvent }) => h("el-button", { on: clickEvent }, '编辑'),
delRender: ({ h, clickEvent }) => h("el-button", { on: clickEvent }, '删除')
},
page: {
enable: true,
height: 45,
layout: "total, prev, pager, next, jumper, sizes",
background: true
},
// query 别名
queryProps: {
currentPage: "page",
pageSize: "size",
orderColumn: 'sortProp',
order:"sortOrder"
},
// table empty 插槽
slotEmpty: function (h) {
return h('el-empty', { props: { description: "暂无数据" } });
}
}
Vue.use(agelTable,tableConfig)
// use 注册组件 OR component 注册组件
Vue.prototype.$agelTableConfig = tableConfig;
Vue.component('agel-table', agelTable);
# 表格配置
# table
表格属性配置。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
...... | ...... | ...... | All Element-ui Table Attributes (opens new window) |
loading | Boolean | false | 是否开启加载状态 |
data | Array | [ ] | 数据 |
columns | Array/Object | [ ] | 列配置 |
query | Object | { } | 查询参数,默认包含分页排序参数 |
on | Object | { } | table 和 page 组件的 Event 事件 |
request | Function | - | 接口数据代理函数 |
page | Object | - | 分页配置 |
menu | Object | - | 菜单列配置 |
merge | Object | - | 自动合并单元格 |
virtual | Object | - | 大数据虚拟滚动 |
resize | Object | - | 随窗口大小自适应高度 |
# column
表格列扩展属性。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
...... | ...... | ...... | All Element-ui Table-column Attributes (opens new window) |
display | Boolean/Function | true | 是否显示该列 |
merge | Boolean | false | 该列相同行是否自动合并 |
children | Array | - | 配置多级表头 |
slotColumn | String/Function | - | 自定义表列的插槽名称 / slotColumn(h,scope) |
slotHeader | String/Function | - | 自定义表头的插槽名称 / slotHeader(h,scope) |
# page
开启分页配置,基础属性建议配置在全局。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
...... | ...... | All Element-ui Pagination Attributes | ...... |
enable | Boolean | false | 是否开启分页 |
height | Nnmber | 45 | 占据高度 |
justify | String | flex-end | 对齐方式 |
layout | String | 'total, sizes, prev, pager, next, jumper' | 组件布局 |
pageSizes | Array | [10, 20, 50, 100] | 页码选项设置 |
pageSize | Nnmber | 20 | 每页显示条目个数 |
currentPage | Nnmber | 1 | 当前页 |
total | Nnmber | 0 | 总条目数 |
# menu
开启菜单列,editRender
delRender
等基础属性建议配置在全局。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
...... | ...... | ...... | All Element-ui Table-column Attributes (opens new window) |
enable | Boolean | false | 是否开启菜单列 |
insertIndex | Number | - | 菜单列插入位置,默认在结尾 |
onEdit | Function | - | 菜单编辑按钮点击回调,设置后显示编辑按钮 |
onDel | Function | - | 菜单删除按钮点击回调,设置后显示删除按钮 |
editRender | Function | - | 自定义编辑按钮, editRender({h,clickEvent}) |
delRender | Function | - | 自定义删除按钮, delRender({h,clickEvent}) |
menuRender | Function | - | 自定义菜单按钮, menuRender({h,scope,menu}) |
# merge
开启自动合并单元格。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
enable | Boolean | false | 是否开启合并单元格 |
auto | Boolean | false | 是否自动合并相同单元格 |
direction | String | vertical | 合并方向,可选 vertical horizontal |
# virtual
开启虚拟滚动。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
enable | Boolean | false | 是否开启虚拟滚动 |
rowHeight | Number | 0 | 行高度 |
# resize
开启高度自适应容器。
属性 | 类型 | 默认值 | 说明 |
---|---|---|---|
enable | Boolean | false | 是否开启自适应 |
relative | Stribg/Dom | table.offsetParent | 自适应参照物元素或者选择器 |
offset | Number/Function | 0 | calcHeight 偏移高度 |
# methods
和传统的通过 $refs.table.xxx()
来调用组件方法有所不同,在 ageltable 中方法会自动注入到 table 对象中,可以直接通过 table.xxx()
来调用。
属性 | 参数 | 说明 | 备注 |
---|---|---|---|
getRef | - | 获取组件实例 | |
getCol | prop | 获取 column 列对象 | |
getData | {currentPage} | 触发调用 request | request 配置 done 参数可用 |
resizeTable | - | 刷新自适应表格 | resize 开启可用 |
getVirtualRowIndex | - | 获取虚拟滚动中当前 Index | virtual 开启可用 |
virtualScrollToRow | index/row | 滚动到指定行 | virtual 开启可用 |