SimpleTable 简单表格
SimpleTable 是一款非常轻量的表格组件,只使用HTML table
实现所有功能。
WARNING
Vitepress默认主题对组件样式有一定干扰,但不影响功能。
基础样式
文本溢出设置参考
用户名 | 年龄 | 单位 | 简介 | 操作 | |
---|---|---|---|---|---|
柏庐 | 20 | 某个公司 | 来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计 | ||
军结 | 22 | 某个公司 | 经验丰富的前端工程师 | ||
钞洋 | 28 | 某个公司 | 90后交互设计师 |
示例代码
<template>
<epp-simple-table :cols="cols" :data="tableData" @row-click="rowClicked" @cell-click="cellClicked">
<template #firstCol>
<el-checkbox v-model="selectedAll" :indeterminate="isIndeterminate" @change="selectAll" />
</template>
<template #tableIndex="{ row }">
<el-checkbox v-model="selectedRows" :value="row.id" @change="selectRow(row.id)">{{ '' }}</el-checkbox>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import type { ColumnType } from 'element-plus-plus';
const selectedAll = ref(false);
const selectedRows = ref<number[]>([]);
const isIndeterminate = ref(false);
const tableData = ref([
{
id: 1,
name: '柏庐',
sex: '女',
org: '某个公司',
des: '来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计',
otherInfo: {
age: 20,
},
},
{
id: 2,
name: '军结',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
otherInfo: {
age: 22,
},
},
{
id: 3,
name: '钞洋',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
otherInfo: {
age: 28,
},
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex', headerSlotName: 'firstCol', width: '3em' },
{ title: '用户名', prop: 'name' },
{ title: '年龄', prop: 'otherInfo.age' },
{ title: '单位', prop: 'org', align: 'center' },
{
title: '简介',
prop: 'des',
align: 'center',
showTooltip: true,
width: '40%',
tooltipProps: { width: '200px', popperClass: 'test-tip' },
},
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const selectAll = () => {
if (selectedAll.value) {
selectedRows.value.splice(0, selectedRows.value.length);
selectedRows.value.push(...tableData.value.map((d) => d.id));
isIndeterminate.value = false;
} else {
selectedRows.value.splice(0, selectedRows.value.length);
}
};
const selectRow = () => {
selectedAll.value = selectedRows.value.length === tableData.value.length;
if (selectedRows.value.length > 0 && selectedAll.value == false) {
isIndeterminate.value = true;
} else {
isIndeterminate.value = false;
}
};
const rowClicked = (row: Record<string, any>, rowIndex: number, event: Event) => {
console.log('rowClicked', row, rowIndex, event);
};
const cellClicked = (row: Record<string, any>, col: ColumnType, rowIndex: number, colIndex: number, event: Event) => {
console.log('cellClicked', row, col, rowIndex, colIndex, event);
};
</script>
边框样式
border
属性可为表格加上设置边框样式
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
示例代码
<template>
<el-select v-model="value" clearable placeholder="请选择" class="w-200 m-b-lg">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<epp-simple-table :cols="cols" :data="tableData" :border="value" padding="0">
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const options = ref([
{
value: 'borderless',
label: 'borderless',
},
{
value: 'border-x',
label: 'border-x',
},
{
value: 'border-y',
label: 'border-y',
},
{
value: 'bordered',
label: 'bordered',
},
]);
const value = ref('borderless');
</script>
间距设置
padding
属性可为表格加上设置不同的间距尺寸, 同时cell-padding
可设置TD的间距尺寸
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
示例代码
<template>
<el-select v-model="value" clearable placeholder="请选择表格填充" class="m-b-md w-200">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-select v-model="value2" clearable placeholder="请选择单元格填充" class="m-l-md m-b-md w-200">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<epp-simple-table :cols="cols" :data="tableData" border="border-x" :padding="value" :cell-padding="value2">
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const options = ref([
{
value: '0',
label: 'none',
},
{
value: '8px',
label: '8px',
},
{
value: '12px',
label: '12px',
},
{
value: '16px',
label: '16px',
},
{
value: '20px',
label: '20px',
},
{
value: '24px',
label: '24px',
},
]);
const value = ref('0');
const value2 = ref('0');
</script>
悬停样式 Hover
hover
属性可以在悬停在某一行时,呈现背景色。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
示例代码
<template>
<epp-simple-table :cols="cols" :data="tableData" cross-hover hover>
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
</script>
条纹样式
stripe
属性可以创建条纹的表格,以便区分出不同行的数据。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
stripe 还接收 even
或者 odd
属性来设置条纹显示的顺序。默认为 odd
奇数
<template>
<epp-simple-table :cols="cols" :data="tableData" stripe>
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
</script>
尺寸修饰
size
属性可以设置表格的尺寸。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
示例代码
<template>
<el-select v-model="value" clearable placeholder="请选择" class="m-b-md w-200">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<epp-simple-table :cols="cols" :data="tableData" :size="value" class="borderless-last">
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const options = ref([
{
value: 'sm',
label: 'sm',
},
{
value: 'md',
label: 'md',
},
{
value: 'lg',
label: 'lg',
},
]);
const value = ref('md');
</script>
拖拽改变列宽
resize
属性设置为 true
,可以拖拽表格头的列,从而改变列宽。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
示例代码
<template>
<epp-simple-table :cols="cols" :data="tableData" border="bordered" resize>
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex', width: '4em' },
{ title: '用户名', prop: 'name', width: '8em' },
{ title: '性别', prop: 'sex', width: '4em' },
{ title: '单位', prop: 'org', width: '' },
{ title: '简介', prop: 'des', width: '' },
{ title: '操作', slotName: 'handle', align: 'center', width: '6em' },
]);
</script>
列表样式
list
可以将传统的表格呈现成列表的状态。
列表样式会为每一行表格加上圆角,你也可以自定义每一行的间距,例如:gap="var(--xs)"
<template>
<div style="background-color: #25303f; height: 240px; padding: 12px;">
<el-scrollbar style="height: 200px">
<epp-simple-table :cols="cols" :data="tableData" gap-y="8px" list fixed-header>
<template #tableIndex="{ row }">
{{ row.icon }}
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</el-scrollbar>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
icon: 'Briefcase',
},
{
id: 2,
name: '李四',
sex: '男',
org: '某个公司',
des: '来自中国',
icon: 'ChartPie',
},
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
icon: 'Archive',
},
{ id: 4, name: '李四2', sex: '男', org: '某个公司', des: '来自中国', icon: 'Archive' },
{ id: 5, name: '李四3', sex: '男', org: '某个公司', des: '来自中国', icon: 'Archive' },
{ id: 6, name: '李四4', sex: '男', org: '某个公司', des: '来自中国', icon: 'Archive' },
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
</script>
固定表头
为 SimpleTable 组件加上 fixed-header
属性可以使表头固定在顶端。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! | |
4 | 李四2 | 男 | 某个公司 | 来自中国 | |
5 | 李四3 | 男 | 某个公司 | 来自中国 | |
6 | 李四4 | 男 | 某个公司 | 来自中国 |
示例代码
<template>
<div class="table-scroll" style="height: 200px">
<epp-simple-table :cols="cols" :data="tableData" border="bordered" fixed-header>
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
{ id: 4, name: '李四2', sex: '男', org: '某个公司', des: '来自中国' },
{ id: 5, name: '李四3', sex: '男', org: '某个公司', des: '来自中国' },
{ id: 6, name: '李四4', sex: '男', org: '某个公司', des: '来自中国' },
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
</script>
固定列
- 为某一列增加
fixed
属性可以使它固定,同时你可以传递left
right
来控制它固定在什么地方。例如fixed: 'left'
。 fixed
属性还可以为object
类型,详细控制fixed
的距离。在fixed
为object
类型时,distance
字段可以设置成auto
,这样将会根据列宽自动计算应固定的距离。- 建议使用时,
distance
要么都设置具体数值,要么都设置成auto
,混用可能会导致计算错误。
序号 | 姓名 | 性别 | 工号 | 职级 | 司龄 | 字段1 | 字段2 | 右自动固定 | 描述 | 单位 | 操作 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 王二麻子 | 男 | 478343 | P8 | 10 | 测试字段1 | 测试字段2 | 测试字段3 | 来自中国南方的温暖城市! | 某个公司 | |
2 | 李四 | 男 | 238343 | P6 | 3 | 测试字段1 | 测试字段2 | 测试字段3 | 来自中国 | 某个公司 | |
3 | 张三 | 男 | 178343 | P7 | 5 | 测试字段1 | 测试字段2 | 测试字段3 | 来自中国北方的寒冷的城市! | 某个公司 |
示例代码
<template>
<div class="table-scroll scroll-column">
<epp-simple-table :cols="cols" :data="tableData" border="border-x">
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
no: '478343',
level: 'P8',
years: 10,
field1: '测试字段1',
field2: '测试字段2',
field3: '测试字段3',
},
{
id: 2,
name: '李四',
sex: '男',
org: '某个公司',
des: '来自中国',
no: '238343',
level: 'P6',
years: 3,
field1: '测试字段1',
field2: '测试字段2',
field3: '测试字段3',
},
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
no: '178343',
level: 'P7',
years: 5,
field1: '测试字段1',
field2: '测试字段2',
field3: '测试字段3',
},
]);
// 序号 slot名称唯一 tableIndex。 width: 设置宽度。align: 对齐方式。showTooltip: td是否一行显示,超出tooptip
const cols = ref([
{ title: '序号', prop: '', slotName: 'tableIndex', fixed: 'left', minWidth: '50px' },
{ title: '姓名', prop: 'name', showTooltip: true, minWidth: '150px' },
{ title: '性别', prop: 'sex', width: '50px' },
{ title: '工号', prop: 'no', showTooltip: true, minWidth: '120px', fixed: { position: 'left', distance: 'auto' } },
{ title: '职级', prop: 'level' },
{ title: '司龄', prop: 'years' },
{ title: '字段1', prop: 'field1' },
{ title: '字段2', prop: 'field2' },
{ title: '右自动固定', prop: 'field3', fixed: { position: 'right', distance: 'auto' } },
{ title: '描述', prop: 'des', showTooltip: true, minWidth: '400px' },
{ title: '单位', prop: 'org', showTooltip: true, minWidth: '150px', fixed: { position: 'right', distance: 'auto' } },
{
title: '操作',
prop: '',
slotName: 'handle',
align: 'center',
fixed: 'right',
},
]);
</script>
固定行
通过 cellStyle
属性还可以实现固定行效果。
序号 | 姓名 | 性别 | 单位 | 描述 | 操作 |
---|---|---|---|---|---|
0 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
3 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
4 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
5 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
6 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
7 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
8 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
9 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
10 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
11 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
12 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
13 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
14 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
15 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
16 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
17 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
18 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
19 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
20 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
21 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! |
示例代码
<template>
<div class="table-scroll" style="height: 200px">
<epp-simple-table :cols="cols" :data="tableData" border="border-x" fixed-header :cell-style="cellStyle">
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
let idx = 0;
const row = {
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
};
const tableData = ref(new Array(22).fill(0).map((_) => Object.assign(JSON.parse(JSON.stringify(row)), { id: idx++ })));
const cols = ref([
{ title: '序号', prop: '', slotName: 'tableIndex' },
{ title: '姓名', prop: 'name', showTooltip: true, width: '100px' },
{ title: '性别', prop: 'sex', width: '50px' },
{ title: '单位', prop: 'org', showTooltip: true, width: '150px' },
{ title: '描述', prop: 'des', showTooltip: true, width: '400px' },
{ title: '操作', prop: '', slotName: 'handle', align: 'center' },
]);
// 固定5倍数的行
const cellStyle = ({ rowIndex }: { rowIndex: number }) => {
return rowIndex % 5 === 0
? {
backgroundColor: 'var(--el-fill-color-darker)',
zIndex: 10,
position: 'sticky',
top: `48px`, // 48为表格头的高度
}
: {};
};
</script>
固定头和列
表头和列可以同时设置固定。
示例代码
<template>
<el-scrollbar height="200px">
<epp-simple-table :cols="cols" :data="tableData" border="border-x" fixed-header>
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</el-scrollbar>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{ id: 1, name: '费文轩', sex: '男', org: '14933867329', des: '安徽省六安市东港镇港下锡港东路8栋1204室' },
{ id: 2, name: '刘林', sex: '男', org: '11381484641', des: '内蒙锡林浩特市北六门村南河街8栋1204室' },
{ id: 3, name: '金玥傲', sex: '男', org: '15000688905', des: '黑龙江省北安市三岔路浦沅宿舍131号' },
{ id: 4, name: '王武', sex: '男', org: '18102220035', des: '湖北省洪湖市东五条路林机小区948号' },
{ id: 5, name: '卞嘉怡', sex: '女', org: '11022218210', des: '山东省招远市并州北路2条8号' },
{ id: 6, name: '和文杰', sex: '男', org: '12548097666', des: '陕西省安康市金国里506号517房' },
{ id: 7, name: '潘瑞堂', sex: '男', org: '12065726257', des: '安徽省天长市金霞街道国际商业中心121号' },
{ id: 8, name: '关爽', sex: '女', org: '15570593023', des: '四川省简阳市前进路506号517房' },
]);
// 序号 slot名称唯一 tableIndex。 width: 设置宽度。align: 对齐方式。showTooltip: td是否一行显示,超出tooptip
const cols = ref([
{ title: '#', prop: '', slotName: 'tableIndex', minWidth: '4em' },
{ title: '姓名', prop: 'name', minWidth: '7em', fixed: 'left' },
{ title: '性别', prop: 'sex', minWidth: '6em' },
{ title: '手机号', prop: 'org', minWidth: '10em' },
{ title: '住址', prop: 'des', minWidth: '26em' },
{
title: '操作',
prop: '',
slotName: 'handle',
align: 'center',
fixed: 'right',
},
]);
</script>
下拉加载更多
配合 Scrollbar 组件可实现下拉加载更多。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! | |
4 | 张三2 | 男 | 某个公司 | 来自中国北方的寒冷的城市! | |
Loading |
示例代码
<template>
<div ref="divWrapper" style="height: 200px; overflow-y: scroll">
<epp-simple-table :cols="cols" :data="tableData" border="border-x" fixed-header>
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
<template v-if="hadMoreData" #more>
<template v-if="loading">
<el-space size="large">
<epp-spinner size="16px" />
<span>正在加载...</span>
</el-space>
</template>
</template>
</epp-simple-table>
</div>
</template>
<script setup lang="ts">
import { computed, ref, toRefs, watch } from 'vue';
import { useScroll } from '@vueuse/core';
const divWrapper = ref();
let count = 1;
function id() {
return count++;
}
const data = [
{
id: id(),
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: id(), name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: id(),
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
{
id: id(),
name: '张三2',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
];
const loading = ref(false);
const tableData = ref(JSON.parse(JSON.stringify(data)));
const cols = ref([
{ title: '#', slotName: 'tableIndex', width: '8%' },
{ title: '用户名', prop: 'name', width: '15%' },
{ title: '性别', prop: 'sex', width: '8%' },
{ title: '单位', prop: 'org', width: '20%' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center', width: '10%' },
]);
const hadMoreData = computed(() => tableData.value.length < 12);
const loadMore = () => {
if (loading.value || !hadMoreData.value) return;
loading.value = true;
window.setTimeout(() => {
const moreData = JSON.parse(JSON.stringify(data));
moreData.forEach((d: any) => {
d.id = id();
d.name = d.name + d.id;
});
tableData.value.push(...moreData);
loading.value = false;
}, 300);
};
const { arrivedState } = useScroll(divWrapper, { behavior: 'smooth' });
const { bottom } = toRefs(arrivedState);
watch(bottom, () => {
if (bottom.value) {
loadMore();
}
});
</script>
移除表头
show-header
属性可以移除表头,让其展示为一个纯列表样式。
1 | 王二麻子 | 男 | 某个公司 | 来自中国南方的温暖城市! | |
2 | 李四 | 男 | 某个公司 | 来自中国 | |
3 | 张三 | 男 | 某个公司 | 来自中国北方的寒冷的城市! |
示例代码
<template>
<epp-simple-table :cols="cols" :data="tableData" hover :show-header="false">
<template #tableIndex="{ rowIndex }">
<span>{{ rowIndex + 1 }}</span>
</template>
<template #handle>
<el-button link type="primary">修改</el-button>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{ id: 2, name: '李四', sex: '男', org: '某个公司', des: '来自中国' },
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des' },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
</script>
排序
可以通过连续点击相同的排序图标恢复默认排序。如果想自定义列头,但仍然使用默认排序图标,在非setup语法下从 SimpleTable 组件中解构出 SortableIcon 组件;setup语法请参考如下源码。
自定义列 | 用户名 | 性别 | 单位 | 简介 |
---|---|---|---|---|
1 | 范xxxx | 女 | 某个公司 | 来自安全应急UED的设计师来自安全应急UED的设计 |
2 | xxx | 男 | 某个公司 | 经验丰富的前端工程师 |
3 | 王ssss | 男 | 某个公司 | 90后交互设计师 |
列中可以设置sortable属性,值为:true / false / 'descending' / 'ascending'
,并通过监听sort-change事件处理数据排序
<template>
<epp-simple-table :cols="cols" :data="tableData" @sort-change="sortChange">
<template #index>
自定义列
<EppSimpleTable.SortableIcon sortable @sort-change="(val) => sortChange('id', val)" />
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { EppSimpleTable } from 'element-plus-plus';
const defaultData = [
{
id: 1,
name: '范xxxx',
sex: '女',
org: '某个公司',
des: '来自安全应急UED的设计师来自安全应急UED的设计',
},
{
id: 2,
name: 'xxx',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
},
{
id: 3,
name: '王ssss',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
},
];
const tableData = ref(JSON.parse(JSON.stringify(defaultData)));
const cols = ref([
{ title: '序号', prop: 'id', headerSlotName: 'index' },
{ title: '用户名', prop: 'name', sortable: true },
{ title: '性别', prop: 'sex', sortable: false },
{ title: '单位', prop: 'org', sortable: 'descending' },
{
title: '简介',
prop: 'des',
showTooltip: true,
width: '40%',
tooltipProps: { width: '200px', popperClass: 'test-tip' },
sortable: 'ascending',
},
]);
const sortChange = (prop: string, sort: string) => {
// 仅作为示例,实际项目需要通过调取后台API实现
console.log('soring...', prop, sort);
if (sort) {
tableData.value.sort((d1: any, d2: any) => {
const result = String(d1[prop]).localeCompare(String(d2[prop]));
return sort === 'ascending' ? result : result * -1;
});
} else {
tableData.value = JSON.parse(JSON.stringify(defaultData));
}
};
</script>
筛选
如果想自定义列头,但仍然使用默认排序图标,在非setup语法下从 SimpleTable 组件中解构出 FilterIcon 组件;setup语法请参考如下源码。
自定义列 | 用户名 | 单位 | 简介 | 操作 |
---|---|---|---|---|
1 | 范xx | 某个公司 | 来自安全应急UED的设计师来自安全应急UED的设计 | |
2 | xxx | 某个公司 | 经验丰富的前端工程师 | |
3 | 王xxx | 某个公司 | 90后交互设计师 |
列中可以设置 filter
对象,提供 slotName
(必选)、placement
(参考Popover文档)、popperClass
属性。slot中提供 close
方法用来手工关闭弹出框。
<template>
<epp-simple-table :cols="cols" :data="tableData">
<template #filterSlot="{ close }">
<el-space direction="vertical" size="large">
<el-space direction="vertical" size="large">
<el-checkbox v-mode="selectedItems" value="1">条件1</el-checkbox>
<el-checkbox v-mode="selectedItems" value="2">条件2</el-checkbox>
<el-checkbox v-mode="selectedItems" value="3">条件3</el-checkbox>
</el-space>
<el-button type="primary" size="sm" class="m-t-md" @click="close">确定</el-button>
</el-space>
</template>
<template #index>
自定义列
<EppSimpleTable.FilterIcon placement="right">
<template #default="{ close }">
<el-space direction="vertical" size="large">
<el-space direction="vertical" size="large">
<el-checkbox v-mode="selectedItems" value="1">条件1</el-checkbox>
<el-checkbox v-mode="selectedItems" value="2">条件2</el-checkbox>
<el-checkbox v-mode="selectedItems" value="3">条件3</el-checkbox>
</el-space>
<el-button type="primary" size="sm" class="m-t-md" @click="close">确定</el-button>
</el-space>
</template>
</EppSimpleTable.FilterIcon>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { EppSimpleTable } from 'element-plus-plus';
const tableData = ref([
{
id: 1,
name: '范xx',
sex: '女',
org: '某个公司',
des: '来自安全应急UED的设计师来自安全应急UED的设计',
},
{
id: 2,
name: 'xxx',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
},
{
id: 3,
name: '王xxx',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
},
]);
const cols = ref([
{ title: '序号', prop: 'id', headerSlotName: 'index' },
{
title: '用户名',
prop: 'name',
filter: {
slotName: 'filterSlot',
placement: 'top',
popperClass: 'test-filter-slot',
},
},
{ title: '单位', prop: 'org' },
{
title: '简介',
prop: 'des',
showTooltip: true,
width: '40%',
tooltipProps: { width: '200px', popperClass: 'test-tip' },
filter: { slotName: 'filterSlot' },
},
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const selectedItems = ref<string[]>([]);
</script>
高亮行
选择单行数据时使用色块表示。
用户名 | 性别 | 单位 | 简介 | 操作 | |
---|---|---|---|---|---|
1 | 范xxxx | 女 | 某个公司 | 来自安全应急UED的设计师来自安全应急UED的设计 | |
2 | xxx | 男 | 某个公司 | 经验丰富的前端工程师 | |
3 | 王ssss | 男 | 某个公司 | 90后交互设计师 |
SimpleTable 组件提供了单选的支持, 只需要配置highlight-current-row
属性即可实现单选。 之后由current-change
事件来管理选中时触发的事件,它会传入 currentRow,oldCurrentRow。
<template>
<epp-simple-table
ref="tableRef"
:cols="cols"
:data="tableData"
highlight-current-row
@current-change="currentChange"
@row-click="rowClick"
/>
<br />
<el-button class="m-r-md" @click="setCurrent(tableData[0])">选中第一行</el-button>
<el-button @click="setCurrent()">取消选择</el-button>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableRef = ref();
const tableData = ref([
{
id: 1,
name: '范xxxx',
sex: '女',
org: '某个公司',
des: '来自安全应急UED的设计师来自安全应急UED的设计',
},
{
id: 2,
name: 'xxx',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
},
{
id: 3,
name: '王ssss',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
},
]);
const cols = ref([
{ title: '序号', prop: 'id', headerSlotName: 'index' },
{
title: '用户名',
prop: 'name',
sortable: true,
filter: {
slotName: 'filterSlot',
placement: 'top',
popperClass: 'test-filter-slot',
},
},
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{
title: '简介',
prop: 'des',
showTooltip: true,
width: '40%',
tooltipProps: { width: '200px', popperClass: 'test-tip' },
filter: { slotName: 'filterSlot' },
},
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const currentChange = (now: Record<string, any>, old: Record<string, any>) => {
console.log(now, old);
};
const rowClick = () => {
console.log('row-click');
};
const setCurrent = (row?: Record<string, any>) => {
tableRef.value.setCurrentRow(row);
};
</script>
展开行
当行内容过多并且不想显示横向滚动条时,可以使用 SimpleTable 展开行功能。可以定义多列同时展开。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
点我展开 / 范xx | 女 | 某个公司 | 来自安全应急UED的设计师来自安全应急UED的设计 | ||
某个公司 / 来自安全应急UED的设计师来自安全应急UED的设计 | |||||
点我展开 / xxx | 男 | 某个公司 | 经验丰富的前端工程师 | ||
手工展开数据 | |||||
点我展开 / 王xx | 男 | 某个公司 | 90后交互设计师 |
通过设置 expand 对象 和 slot 可以开启展开行功能。expand有两个属性:slotName
,hideLabel
,hideLabel默认为false
<template>
<epp-simple-table ref="tableRef" :cols="cols" :data="tableData" :expand-row-keys="['1index', '2nameExpand']">
<template #index="{ row }">
<p>{{ row.org }} / {{ row.des }}</p>
</template>
<template #name="{ row }"> <a href="javascript:;" @click="expand(row)">点我展开</a> / {{ row.name }} </template>
<template #nameExpand>
<p>手工展开数据</p>
</template>
<template #des="{ row }">
<p>{{ row.sex }} / {{ row.des }}</p>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableRef = ref();
const tableData = ref([
{
id: 1,
name: '范xx',
sex: '女',
org: '某个公司',
des: '来自安全应急UED的设计师来自安全应急UED的设计',
},
{
id: 2,
name: 'xxx',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
},
{
id: 3,
name: '王xx',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
},
]);
const cols = ref([
{ title: '#', prop: 'id', expand: { slotName: 'index', hideLabel: true } },
{ title: '用户名', prop: 'name', slotName: 'name', expand: { slotName: 'nameExpand' } },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{
title: '简介',
prop: 'des',
showTooltip: true,
width: '40%',
expand: { slotName: 'des' },
tooltipProps: { width: '200px', popperClass: 'test-tip' },
},
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const expand = (row: { id: number }) => {
tableRef.value.toggleExpand(row.id, 'nameExpand');
};
</script>
树形数据与懒加载
支持树类型的数据的显示。 当 row 中包含 children 字段时,被视为树形数据。 渲染树形数据时,必须要指定 row-key。支持子节点数据异步加载。 设置 Table 的加载函数 load 。 通过指定 row 中的hasChildren字段来指定哪些行是包含子节点。 children与hasChildren都可以通过 tree-props
配置。first-column-index
属性用来设置展开行为所作用的列。
ID | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
ID | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
当children字段有数组值时,将会忽略hasChildren字段。需要异步加载数据时,一定要谨慎设置default-expand-all
属性为true值
<template>
<epp-simple-table :cols="cols" :data="tableData" :load="load" :expand-row-keys="['1']">
<template #tableIndex="{ row }">
<span>{{ row.id }}</span>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
<br /><br />
<epp-simple-table :cols="cols" :data="tableData" :load="load" :expand-row-keys="['1']" :first-column-index="1">
<template #tableIndex="{ row }">
<span>{{ row.id }}</span>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { isClient } from '@vueuse/core';
let count = 10000;
const tableData = ref();
const cols = ref([
{ title: 'ID', slotName: 'tableIndex' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org' },
{ title: '简介', prop: 'des', width: '220px', showTooltip: true },
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const load = (_: Record<string, any>, __: Record<string, any>, resolve: (data: Record<string, any>[]) => void) => {
window.setTimeout(() => {
resolve([
{
id: count++,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市哦!',
hasChildren: true,
},
{
id: count++,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
children: [
{
id: count++,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
],
},
]);
}, 3000);
};
if (isClient) {
window.setTimeout(() => {
tableData.value = [
{
id: 1,
name: '王二麻子',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市啊!',
children: [
{
id: 11,
name: '王二麻子11',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
children: [
{
id: 111,
name: '王二麻子111',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
{
id: 112,
name: '王二麻子112',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
},
],
},
{
id: 12,
name: '王二麻子12',
sex: '男',
org: '某个公司',
des: '来自中国南方的温暖城市!',
children: [],
},
],
},
{
id: 2,
name: '李四',
sex: '男',
org: '某个公司',
des: '来自中国',
hasChildren: true,
},
{
id: 3,
name: '张三',
sex: '男',
org: '某个公司',
des: '来自中国北方的寒冷的城市!',
},
];
}, 100);
}
</script>
合并行或列
多行或多列共用一个数据时,可以合并行或列。
id | 用户名 | Amount1 | Amount2 | Amount3 |
---|---|---|---|---|
12987122 | 234 | 3.2 | 10 | |
12987123 | Tom | 165 | 4.43 | 12 |
12987124 | 324 | 1.9 | 9 | |
12987125 | Tom | 621 | 2.2 | 17 |
12987126 | 539 | 4.1 | 15 |
id | 用户名 | Amount1 | Amount2 | Amount3 |
---|---|---|---|---|
12987122 | Tom | 234 | 3.2 | 10 |
Tom | 165 | 4.43 | 12 | |
12987124 | Tom | 324 | 1.9 | 9 |
Tom | 621 | 2.2 | 17 | |
12987126 | Tom | 539 | 4.1 | 15 |
通过给 table 传入span-method方法可以实现合并行或列, 方法的参数是一个对象,里面包含当前行 row、当前列 column、当前行号 rowIndex、当前列号 columnIndex 四个属性。 该函数可以返回一个包含两个元素的数组,第一个元素代表 rowspan,第二个元素代表 colspan。 也可以返回一个键名为 rowspan 和 colspan 的对象。
<template>
<epp-simple-table :cols="cols" :data="tableData" border="bordered" :span-method="arraySpanMethod" />
<epp-simple-table :cols="cols" :data="tableData" border="bordered" class="m-t-md" :span-method="objectSpanMethod" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: '12987122',
name: 'Tom',
amount1: '234',
amount2: '3.2',
amount3: 10,
},
{
id: '12987123',
name: 'Tom',
amount1: '165',
amount2: '4.43',
amount3: 12,
},
{
id: '12987124',
name: 'Tom',
amount1: '324',
amount2: '1.9',
amount3: 9,
},
{
id: '12987125',
name: 'Tom',
amount1: '621',
amount2: '2.2',
amount3: 17,
},
{
id: '12987126',
name: 'Tom',
amount1: '539',
amount2: '4.1',
amount3: 15,
},
]);
const cols = ref([
{ title: 'id', prop: 'id' },
{ title: '用户名', prop: 'name' },
{ title: 'Amount1', prop: 'amount1' },
{ title: 'Amount2', prop: 'amount2' },
{ title: 'Amount3', prop: 'amount3' },
]);
const arraySpanMethod = ({ rowIndex, columnIndex }: { rowIndex: number; columnIndex: number }) => {
if (rowIndex % 2 === 0) {
if (columnIndex === 0) {
return [1, 2];
} else if (columnIndex === 1) {
return [0, 0];
}
}
};
const objectSpanMethod = ({ rowIndex, columnIndex }: { rowIndex: number; columnIndex: number }) => {
if (columnIndex === 0) {
if (rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1,
};
} else {
return {
rowspan: 0,
colspan: 0,
};
}
}
};
</script>
多级表头
数据结构比较复杂的时候,可使用多级表头来展现数据的层次关系。
日期 | 配送信息 | ||||
---|---|---|---|---|---|
姓名 | 地址信息 | ||||
省/市 | 城市 | 地址 | 操作 | ||
2016-05-03 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles | |
2016-05-02 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles | |
2016-05-04 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles | |
2016-05-01 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles | |
2016-05-08 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles | |
2016-05-06 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles | |
2016-05-07 | Tom | California | Los Angeles | No. 189, Grove St, Los Angeles |
通过cols
的 children
属性嵌套实现多级表头
<template>
<epp-simple-table :cols="cols" :data="tableData" border="bordered">
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
date: '2016-05-03',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-02',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-04',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-01',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-08',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-06',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
{
date: '2016-05-07',
name: 'Tom',
state: 'California',
city: 'Los Angeles',
address: 'No. 189, Grove St, Los Angeles',
zip: 'CA 90036',
},
]);
const cols = ref([
{ title: '日期', prop: 'date' },
{
title: '配送信息',
prop: 'delivery',
children: [
{ title: '姓名', prop: 'name' },
{
title: '地址信息',
prop: 'address',
children: [
{ title: '省/市', prop: 'state' },
{ title: '城市', prop: 'city' },
{ title: '地址', prop: 'address' },
{ title: '操作', prop: 'zip', slotName: 'handle' },
],
},
],
},
]);
</script>
表尾合计行
若表格展示的是各类数字,可以在表尾显示各列的合计。
id | 用户名 | Amount1 | Amount2 | Amount3 |
---|---|---|---|---|
12987122 | Tom | 234 | 3.2 | 10 |
12987123 | Tom | 165 | 4.43 | 12 |
12987124 | Tom | 324 | 1.9 | 9 |
12987125 | Tom | 621 | 2.2 | 17 |
12987126 | Tom | 539 | 4.1 | 15 |
合计 | ¥3232 | ¥1212.22 | ¥90.22 |
可以通过自定义 foot
slot实现
<template>
<epp-simple-table :cols="cols" :data="tableData" border="bordered">
<template #foot>
<tr>
<td colspan="2"><strong>合计</strong></td>
<td>¥3232</td>
<td>¥1212.22</td>
<td>¥90.22</td>
</tr>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([
{
id: '12987122',
name: 'Tom',
amount1: '234',
amount2: '3.2',
amount3: 10,
},
{
id: '12987123',
name: 'Tom',
amount1: '165',
amount2: '4.43',
amount3: 12,
},
{
id: '12987124',
name: 'Tom',
amount1: '324',
amount2: '1.9',
amount3: 9,
},
{
id: '12987125',
name: 'Tom',
amount1: '621',
amount2: '2.2',
amount3: 17,
},
{
id: '12987126',
name: 'Tom',
amount1: '539',
amount2: '4.1',
amount3: 15,
},
]);
const cols = ref([
{ title: 'id', prop: 'id' },
{ title: '用户名', prop: 'name' },
{ title: 'Amount1', prop: 'amount1' },
{ title: 'Amount2', prop: 'amount2' },
{ title: 'Amount3', prop: 'amount3' },
]);
</script>
隐藏列
toggleColumn
方法支持对列的隐藏或者显示操作。
# | 用户名 | 性别 | 单位 | 简介 | 操作 |
---|---|---|---|---|---|
1 | 范xxx | 女 | 某个公司 | 来自安全应急UED的设计师来自安全应急 | |
2 | xxx | 男 | 某个公司 | 经验丰富的前端工程师 | |
3 | 王xxxxx | 男 | 某个公司 | 90后交互设计师 |
暂不支持对多级表头以及存在合并单元格的表格进行操作
<template>
<epp-simple-table ref="simpleTableRef" :cols="cols" :data="tableData">
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
<br /><br />
<el-button type="primary" @click="toggleColumn">隐藏/显示第3列</el-button>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const simpleTableRef = ref();
const tableData = ref([
{
id: 1,
name: '范xxx',
sex: '女',
org: '某个公司',
des: '来自安全应急UED的设计师来自安全应急',
},
{
id: 2,
name: 'xxx',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
},
{
id: 3,
name: '王xxxxx',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
},
]);
const cols = ref([
{ title: '#', prop: 'id' },
{ title: '用户名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '单位', prop: 'org', align: 'center' },
{
title: '简介',
prop: 'des',
showTooltip: true,
width: '40%',
tooltipProps: { width: '200px', popperClass: 'test-tip' },
},
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const toggleColumn = () => {
simpleTableRef.value.toggleColumn(2);
};
</script>
拖拽排序
利用Sortablejs实现表格行拖拽移动位置。
用户名 | 年龄 | 单位 | 简介 | 操作 | |
---|---|---|---|---|---|
柏庐 | 20 | 某个公司 | 来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计 | ||
军结 | 22 | 某个公司 | 经验丰富的前端工程师 | ||
钞洋 | 28 | 某个公司 | 90后交互设计师 | ||
钞洋1 | 28 | 某个公司 | 90后交互设计师 | ||
钞洋2 | 28 | 某个公司 | 90后交互设计师 |
示例代码
<template>
<epp-simple-table
:cols="cols"
:data="tableData"
class="sortable-table"
@row-click="rowClicked"
@cell-click="cellClicked"
>
<template #firstCol>
<el-checkbox v-model="selectedAll" :indeterminate="isIndeterminate" @change="selectAll" />
</template>
<template #tableIndex="{ row }">
<el-checkbox v-model="selectedRows" :value="row.id" @change="selectRow(row.id)">{{ '' }}</el-checkbox>
</template>
<template #handle>
<a>修改</a>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref, onMounted, nextTick } from 'vue';
import { isClient } from '@vueuse/core';
import Sortable from 'sortablejs';
import type { ColumnType } from 'element-plus-plus';
const selectedAll = ref(false);
const selectedRows = ref<number[]>([]);
const isIndeterminate = ref(false);
const tableData = ref([
{
id: 1,
name: '柏庐',
sex: '女',
org: '某个公司',
des: '来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计',
otherInfo: {
age: 20,
},
},
{
id: 2,
name: '军结',
sex: '男',
org: '某个公司',
des: '经验丰富的前端工程师',
otherInfo: {
age: 22,
},
},
{
id: 3,
name: '钞洋',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
otherInfo: {
age: 28,
},
},
{
id: 4,
name: '钞洋1',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
otherInfo: {
age: 28,
},
},
{
id: 5,
name: '钞洋2',
sex: '男',
org: '某个公司',
des: '90后交互设计师',
otherInfo: {
age: 28,
},
},
]);
const cols = ref([
{ title: '#', slotName: 'tableIndex', headerSlotName: 'firstCol', width: '3em' },
{ title: '用户名', prop: 'name' },
{ title: '年龄', prop: 'otherInfo.age' },
{ title: '单位', prop: 'org', align: 'center' },
{
title: '简介',
prop: 'des',
align: 'center',
showTooltip: true,
width: '40%',
tooltipProps: { width: '200px', popperClass: 'test-tip' },
},
{ title: '操作', slotName: 'handle', align: 'center' },
]);
const selectAll = () => {
if (selectedAll.value) {
selectedRows.value.splice(0, selectedRows.value.length);
selectedRows.value.push(...tableData.value.map((d) => d.id));
isIndeterminate.value = false;
} else {
selectedRows.value.splice(0, selectedRows.value.length);
}
};
const selectRow = () => {
selectedAll.value = selectedRows.value.length === tableData.value.length;
if (selectedRows.value.length > 0 && selectedAll.value == false) {
isIndeterminate.value = true;
} else {
isIndeterminate.value = false;
}
};
const rowClicked = (row: Record<string, any>, rowIndex: number, event: Event) => {
console.log('rowClicked', row, rowIndex, event);
};
const cellClicked = (row: Record<string, any>, col: ColumnType, rowIndex: number, colIndex: number, event: Event) => {
console.log('cellClicked', row, col, rowIndex, colIndex, event);
};
onMounted(() => {
if (!isClient) return;
const el = document.querySelector('.sortable-table > tbody');
Sortable.create(el, {
disabled: false,
handle: 'tr',
animation: 150,
onEnd: (e: any) => {
const arr = tableData.value;
arr.splice(e.newIndex, 0, arr.splice(e.oldIndex, 1)[0]);
nextTick(() => {
tableData.value = arr;
});
},
});
});
</script>
空数据
序号 | 姓名 | 性别 | 操作 |
---|---|---|---|
No Data |
示例代码
<template>
<epp-simple-table :cols="cols" border="border-x" :data="tableData" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref([]);
// 序号 slot名称唯一 tableIndex。 width: 设置宽度。align: 对齐方式。showTooltip: td是否一行显示,超出tooptip
const cols = ref([
{ title: '序号', prop: '', slotName: 'tableIndex' },
{ title: '姓名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '操作', prop: '', align: 'center' },
]);
</script>
未知数据
序号 | 姓名 | 性别 | 操作 |
---|---|---|---|
可能数据报错了哦~ |
在传递的数据为 null
或者 undefined
时,可以自定义 unknown
slot
<template>
<epp-simple-table :cols="cols" border="border-x" :data="tableData">
<template #unknown>
<p style="text-align: center">可能数据报错了哦~</p>
</template>
</epp-simple-table>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const tableData = ref(null);
// 序号 slot名称唯一 tableIndex。 width: 设置宽度。align: 对齐方式。showTooltip: td是否一行显示,超出tooptip
const cols = ref([
{ title: '序号', prop: '', slotName: 'tableIndex' },
{ title: '姓名', prop: 'name' },
{ title: '性别', prop: 'sex' },
{ title: '操作', prop: '', align: 'center' },
]);
</script>
Attributes
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
row-key | 行数据的 Key,用来优化 SimpleTable 的渲染。如果表格数据标识符不是id字段,请一定要设置此值 | string / function(row): string | - | id |
border | 为表格设置边框样式 | string | borderless/bordered/border-x/border-y | |
padding | 设置表格两端的 padding 尺寸 | string | 通用尺寸标签/自定义尺寸 | |
cell-padding | 设置Td的 padding 尺寸 | string | 通用尺寸标签/自定义尺寸 | |
gap | list模式下,设置表格行间距 | string | css尺寸 | |
gap-x | list模式下,设置表格行横向间距 | string | css尺寸 | |
gap-y | list模式下,设置表格行纵向间距 | string | css尺寸 | |
hover | 表格行悬停效果 | boolean | ||
cross-hover | 表格列悬停效果 | boolean | ||
stripe | 表格条纹效果 | boolean / string | true / false / odd / even | false |
list | 列表样式 | boolean | false | |
auto-height | 使Th和Td的高度变为auto | boolean | false | |
fixed-header | 固定表头 | boolean | - | |
fixed-footer | 固定表尾 | boolean | - | |
show-header | 是否显示表头 | boolean | - | true |
size | 表格大小 | string | sm / md / lg | - |
resize | 是否可以拖拽表头改变列宽 | boolean | - | false |
scroll-container | 设置固定列时,如果滚动容器不是表格的直接父元素或者Scrollbar组件,需要设置此属性,用以支持滚动时固定列阴影效果 | string / HTMLElement | - | - |
highlight-current-row | 是否要高亮当前行 | boolean | - | false |
expand-row-keys | 默认展开,同时适用行展开与树展开。行展开时用行rowKey+slotName作为唯一标识符;树展开时使用rowKey作为唯一标识符。数组值一定是字符串。 | array | - | - |
default-expand-all | 是否默认展开所有行,当 SimpleTable 包含展开行存在或者为树形表格时有效 | boolean | - | false |
row-class-name | 行的 className 的回调方法,也可以使用字符串为所有行设置一个固定的 className。 | function({ row, rowIndex }) / string | - | - |
row-style | 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style。 | function({ row, rowIndex }) / object | - | - |
cell-class-name | 单元格的 className 的回调方法,也可以使用字符串为所有单元格设置一个固定的 className。 | function({ row, column, rowIndex, columnIndex }) / string | - | - |
cell-style | 单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有单元格设置一样的 Style。 | function({ row, column, rowIndex, columnIndex }) / object | - | - |
header-row-class-name | 表头行的 className 的回调方法,也可以使用字符串为所有表头行设置一个固定的 className。 | function({ row, rowIndex }) / string | - | - |
header-row-style | 表头行的 style 的回调方法,也可以使用一个固定的 Object 为所有表头行设置一样的 Style。 | function({ row, rowIndex }) / object | - | - |
header-cell-class-name | 表头单元格的 className 的回调方法,也可以使用字符串为所有表头单元格设置一个固定的 className。 | function({ row, column, rowIndex, columnIndex }) / string | - | - |
header-cell-style | 表头单元格的 style 的回调方法,也可以使用一个固定的 Object 为所有表头单元格设置一样的 Style。 | function({ row, column, rowIndex, columnIndex }) / object | - | - |
span-method | 合并行或列的计算方法 | function({ row, column, rowIndex, columnIndex }) | - | - |
first-column-index | 树形展开操作作用的列 | number | - | 0 |
tree-props | 渲染嵌套数据的配置选项 | object | - | { hasChildren: 'hasChildren', children: 'children' } |
load | 加载子节点数据的函数,函数第二个参数包含了节点的层级信息 | function(row, treeNode, resolve) | - | - |
cols | 列配置,参见下表 | array | - | - |
cols
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
columnKey | 列key,如果动态切换表格列,需要设置此值。否则列宽会计算错误 | string | ||
title | 表格标题 | string | ||
prop | 表格列属性名称 | string | ||
showTooltip | 是否显示 tooltip,需要配合列 width 值使用 | boolean | false | |
tooltipProps | tooltip 属性,参考 Popover 组件 | object | ||
align | 水平对齐方式 | string | left/center/right | left |
width | 列宽 | string | - | |
minWidth | 最小列宽 | string | - | |
maxWidth | 最大列宽 | string | - | |
fixed | 固定列 | string / object | left / right / { position: string; distance: string; } | - |
headerSlotName | 列头 slot 名称,默认参数为 col,请参考示例 | string | - | - |
sortable | 是否为排序列 | boolean / string | true / false / 'ascending' / 'descending' | - |
filter | 列筛选设置 | object{ slotName: string, placement: string, popperClass: string } | - | - |
expand | 展开列设置 | object{ slotName: string, hideLabel: boolean } | - | - |
children | 子列信息 | array | - | - |
formatter | 用来格式化内容 | function(row, column, cellValue, rowIndex, columnIndex) | - | - |
Events
事件名称 | 说明 | 回调参数 |
---|---|---|
row-click | 行单击事件 | row, rowIndex, event |
cell-click | 单元格单击事件 | row, col, rowIndex, colIndex, event |
sort-change | 排序事件 | prop, sort |
current-change | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性 | currentRow, oldCurrentRow |
expand | 展开事件 | expanded, rowkey, slotName |
tree-expand | 树展开事件 | expanded, row |
Methods
方法名 | 说明 | 参数 |
---|---|---|
toggleExpand | 展开/折叠行。由于每行可能有多个展开,所以需要传递需要展开的slotName | rowKey, slotName |
toggleExpandTree | 展开树 | row |
toggleColumn | 显示/隐藏列 | index, show(show可选) |
setCurrentRow | 用于单选表格,设定某一行为选中行, 如果调用时不加参数,则会取消目前高亮行的选中状态 | row |
clearTooltip | 隐藏tooltip | - |
Slots
名称 | 说明 |
---|---|
empty | 无数据时的提示 |
unknown | 表格数据为null或者undefined时,自定义内容 |
more | 下拉加载时,自定义内容 |
foot | 表尾 |