Skip to content

SimpleTable

SimpleTable is a very lightweight table component that uses only HTML table to implement all its features.

TIP

The component needs to be wrapped with <client-only></client-only> tags when used in SSR (e.g., Nuxt) and SSG (e.g., VitePress).

WARNING

The default Vitepress theme has some interference with the component's styles, but it does not affect functionality.

Basic

For text overflow settings, refer to:

用户名
年龄
单位
简介
操作
柏庐
20
某个公司
来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计
军结
22
某个公司
经验丰富的前端工程师
钞洋
28
某个公司
90后交互设计师
Example Code
vue
<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 Style

The border prop can add border styles to the table.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
Example Code
vue
<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>

Spacing Settings

The padding prop can add different spacing sizes to the table, while cell-padding can set the spacing size for TDs.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
Example Code
vue
<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 Style

The hover prop can display a background color when hovering over a row.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
Example Code
vue
<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 Style

The stripe prop can create a striped table to distinguish between different rows of data.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
stripe also accepts even or odd props to set the order of stripe display. The default is odd.
vue
<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 Modifier

The size prop can set the size of the table.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
Example Code
vue
<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>

Drag to Resize Columns

Setting the resize prop to true allows dragging the table header columns to change their width.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
Example Code
vue
<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 Style

list can present the traditional table as a list.

#
用户名
性别
单位
简介
操作
Briefcase
王二麻子
某个公司
来自中国南方的温暖城市!
ChartPie
李四
某个公司
来自中国
Archive
张三
某个公司
来自中国北方的寒冷的城市!
Archive
李四2
某个公司
来自中国
Archive
李四3
某个公司
来自中国
Archive
李四4
某个公司
来自中国
The list style adds rounded corners to each table row. You can also customize the spacing between each row, for example: gap="var(--xs)".
vue
<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>

Fixed Header

Adding the fixed-header prop to the SimpleTable component can fix the header to the top.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
4
李四2
某个公司
来自中国
5
李四3
某个公司
来自中国
6
李四4
某个公司
来自中国
Example Code
vue
<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 Columns

  • Adding the fixed prop to a column can fix it. You can also pass left or right to control where it is fixed. For example, fixed: 'left'.
  • The fixed prop can also be of type object for detailed control of the fixed distance. When fixed is of type object, the distance field can be set to auto, which will automatically calculate the fixed distance based on the column width.
  • It is recommended that when using this, distance should either be set to specific values or set to auto. Mixing them may cause calculation errors.
序号
姓名
性别
工号
职级
司龄
字段1
字段2
右自动固定
描述
单位
操作
1
王二麻子
478343
P8
10
测试字段1
测试字段2
测试字段3
来自中国南方的温暖城市!
某个公司
2
李四
238343
P6
3
测试字段1
测试字段2
测试字段3
来自中国
某个公司
3
张三
178343
P7
5
测试字段1
测试字段2
测试字段3
来自中国北方的寒冷的城市!
某个公司
Example Code
vue
<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>

Fixed Rows

Fixed row effect can also be achieved through the cellStyle prop.

序号
姓名
性别
单位
描述
操作
0
王二麻子
某个公司
来自中国南方的温暖城市!
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
王二麻子
某个公司
来自中国南方的温暖城市!
3
王二麻子
某个公司
来自中国南方的温暖城市!
4
王二麻子
某个公司
来自中国南方的温暖城市!
5
王二麻子
某个公司
来自中国南方的温暖城市!
6
王二麻子
某个公司
来自中国南方的温暖城市!
7
王二麻子
某个公司
来自中国南方的温暖城市!
8
王二麻子
某个公司
来自中国南方的温暖城市!
9
王二麻子
某个公司
来自中国南方的温暖城市!
10
王二麻子
某个公司
来自中国南方的温暖城市!
11
王二麻子
某个公司
来自中国南方的温暖城市!
12
王二麻子
某个公司
来自中国南方的温暖城市!
13
王二麻子
某个公司
来自中国南方的温暖城市!
14
王二麻子
某个公司
来自中国南方的温暖城市!
15
王二麻子
某个公司
来自中国南方的温暖城市!
16
王二麻子
某个公司
来自中国南方的温暖城市!
17
王二麻子
某个公司
来自中国南方的温暖城市!
18
王二麻子
某个公司
来自中国南方的温暖城市!
19
王二麻子
某个公司
来自中国南方的温暖城市!
20
王二麻子
某个公司
来自中国南方的温暖城市!
21
王二麻子
某个公司
来自中国南方的温暖城市!
Example Code
vue
<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>

Fixed Header and Columns

The header and columns can be fixed simultaneously.

#
姓名
性别
手机号
住址
操作
1
费文轩
14933867329
安徽省六安市东港镇港下锡港东路8栋1204室
2
刘林
11381484641
内蒙锡林浩特市北六门村南河街8栋1204室
3
金玥傲
15000688905
黑龙江省北安市三岔路浦沅宿舍131号
4
王武
18102220035
湖北省洪湖市东五条路林机小区948号
5
卞嘉怡
11022218210
山东省招远市并州北路2条8号
6
和文杰
12548097666
陕西省安康市金国里506号517房
7
潘瑞堂
12065726257
安徽省天长市金霞街道国际商业中心121号
8
关爽
15570593023
四川省简阳市前进路506号517房
Example Code
vue
<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>

Pull-Down to Load More

With the Scrollbar component, pull-down to load more can be implemented.

#
用户名
性别
单位
简介
操作
1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
4
张三2
某个公司
来自中国北方的寒冷的城市!
Loading
Example Code
vue
<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>

Remove Header

The show-header prop can remove the header, making it display as a pure list style.

1
王二麻子
某个公司
来自中国南方的温暖城市!
2
李四
某个公司
来自中国
3
张三
某个公司
来自中国北方的寒冷的城市!
Example Code
vue
<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>

Sorting

You can restore the default sorting by continuously clicking the same sorting icon. If you want to customize the column header but still use the default sorting icon, destructure the SortableIcon component from the SimpleTable component in non-setup syntax; for setup syntax, please refer to the following source code.

自定义列
用户名
性别
单位
简介
1
范xxxx
某个公司
来自安全应急UED的设计师来自安全应急UED的设计
2
xxx
某个公司
经验丰富的前端工程师
3
王ssss
某个公司
90后交互设计师
You can set the sortable prop in the column. The value can be: true / false / 'descending' / 'ascending'. Handle data sorting by listening to the sort-change event.
vue
<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>

Filtering

If you want to customize the column header but still use the default sorting icon, destructure the FilterIcon component from the SimpleTable component in non-setup syntax; for setup syntax, please refer to the following source code.

自定义列
用户名
单位
简介
操作
1
范xx
某个公司
来自安全应急UED的设计师来自安全应急UED的设计
2
xxx
某个公司
经验丰富的前端工程师
3
王xxx
某个公司
90后交互设计师
You can set the filter object in the column, providing slotName (required), placement (refer to the Popover documentation), and popperClass properties. The close method is provided in the slot to manually close the pop-up.
vue
<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>

Highlight Row

Use a color block to indicate when a single row of data is selected.

用户名
性别
单位
简介
操作
1
范xxxx
某个公司
来自安全应急UED的设计师来自安全应急UED的设计
2
xxx
某个公司
经验丰富的前端工程师
3
王ssss
某个公司
90后交互设计师

The SimpleTable component provides single selection support. You only need to configure the highlight-current-row prop to achieve single selection. The current-change event then manages the event triggered when selected. It will pass in currentRow and oldCurrentRow.
vue
<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>

Expand Row

When there is too much row content and you don't want to display a horizontal scrollbar, you can use the SimpleTable expand row feature. You can define multiple columns to expand simultaneously.

#
用户名
性别
单位
简介
操作
点我展开 / 范xx
某个公司
来自安全应急UED的设计师来自安全应急UED的设计

某个公司 / 来自安全应急UED的设计师来自安全应急UED的设计

某个公司
经验丰富的前端工程师

手工展开数据

点我展开 / 王xx
某个公司
90后交互设计师
You can enable the expand row feature by setting the expand object and slot. The expand object has two properties: slotName and hideLabel. hideLabel defaults to false.
vue
<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>

Tree Data and Lazy Loading

Supports the display of tree-type data. When a row contains the children field, it is treated as tree data. When rendering tree data, row-key must be specified. Supports asynchronous loading of child node data. Set the Table's loading function load. Specify which rows contain child nodes by specifying the hasChildren field in the row. Both children and hasChildren can be configured through tree-props. The first-column-index prop is used to set the column on which the expand behavior acts.

ID
用户名
性别
单位
简介
操作


ID
用户名
性别
单位
简介
操作
When the children field has an array value, the hasChildren field will be ignored. When you need to load data asynchronously, be sure to carefully set the default-expand-all property to true.
vue
<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>

Merge Rows or Columns

When multiple rows or columns share the same data, you can merge rows or columns.

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
By passing the span-method function to the table, you can merge rows or columns. The function's parameter is an object containing four properties: row (current row), column (current column), rowIndex (current row index), and columnIndex (current column index). The function can return an array containing two elements: the first element represents rowspan, and the second represents colspan. You can also return an object with keys named rowspan and colspan.
vue
<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>

Multi-level Header

When the data structure is complex, you can use a multi-level header to display the hierarchical relationship of the data.

日期
配送信息
姓名
地址信息
省/市
城市
地址
操作
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
Multi-level headers are implemented by nesting the children property of cols.
vue
<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>

If the table displays various numbers, you can display the sum of each column in the table footer.

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
This can be implemented by customizing the foot slot.
vue
<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>

Hide Columns

The toggleColumn method supports hiding or showing columns.

#
用户名
性别
单位
简介
操作
1
范xxx
某个公司
来自安全应急UED的设计师来自安全应急
2
xxx
某个公司
经验丰富的前端工程师
3
王xxxxx
某个公司
90后交互设计师


This feature does not currently support multi-level headers or tables with merged cells.
vue
<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>

Drag and Drop Sorting

Use Sortablejs to implement drag and drop functionality for reordering rows in a table.

用户名
年龄
单位
简介
操作
柏庐
20
某个公司
来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计来自UED的设计师来自UED的设计
军结
22
某个公司
经验丰富的前端工程师
钞洋
28
某个公司
90后交互设计师
钞洋1
28
某个公司
90后交互设计师
钞洋2
28
某个公司
90后交互设计师
Example Code
vue
<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>

Empty Data

序号
姓名
性别
操作
No Data
Example Code
vue
<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>

Unknown Data

序号
姓名
性别
操作

可能数据报错了哦~

You can customize the unknown slot when the passed data is null or undefined.
vue
<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

ParameterDescriptionTypeOptional ValuesDefault Value
row-keyThe key of the row data, used to optimize SimpleTable rendering. If the identifier of the table data is not the id field, you must set this value.string / function(row): string-id
borderSets the border style for the tablestringborderless/bordered/border-x/border-y
paddingSets the padding size on both sides of the tablestring通用尺寸标签/自定义尺寸
cell-paddingSets the padding size of the table cells (TDs)string通用尺寸标签/自定义尺寸
gapSets the row spacing of the table in list modestringcss尺寸
gap-xSets the horizontal row spacing of the table in list modestringcss尺寸
gap-ySets the vertical row spacing of the table in list modestringcss尺寸
hoverEnables row hover effectboolean
cross-hoverEnables column hover effectboolean
stripeEnables table striping effectboolean / stringtrue / false / odd / evenfalse
listEnables list stylebooleanfalse
auto-heightMakes the height of TH and TD elements autobooleanfalse
fixed-headerFixes the table headerboolean-
fixed-footerFixes the table footerboolean-
show-headerWhether to display the table headerboolean-true
sizeSets the table sizestringsm / md / lg-
resizeWhether the column width can be changed by dragging the headerboolean-false
scroll-containerWhen setting fixed columns, if the scrolling container is not the direct parent of the table or a Scrollbar component, this prop needs to be set to support fixed column shadow effects when scrollingstring / HTMLElement--
highlight-current-rowWhether to highlight the current rowboolean-false
expand-row-keysDefault expanded rows, applicable to both row expansion and tree expansion. When expanding rows, rowKey + slotName is used as the unique identifier; when expanding trees, rowKey is used. Array values must be strings.array--
default-expand-allWhether to expand all rows by default. Effective when SimpleTable contains expandable rows or is a tree tableboolean-false
row-class-nameCallback method for the row's className. You can also use a string to set a fixed className for all rowsfunction({ row, rowIndex }) / string--
row-styleCallback method for the row's style. You can also use a fixed Object to set the same Style for all rowsfunction({ row, rowIndex }) / object--
cell-class-nameCallback method for the cell's className. You can also use a string to set a fixed className for all cellsfunction({ row, column, rowIndex, columnIndex }) / string--
cell-styleCallback method for the cell's style. You can also use a fixed Object to set the same Style for all cellsfunction({ row, column, rowIndex, columnIndex }) / object--
header-row-class-nameCallback method for the header row's className. You can also use a string to set a fixed className for all header rowsfunction({ row, rowIndex }) / string--
header-row-styleCallback method for the header row's style. You can also use a fixed Object to set the same Style for all header rowsfunction({ row, rowIndex }) / object--
header-cell-class-nameCallback method for the header cell's className. You can also use a string to set a fixed className for all header cellsfunction({ row, column, rowIndex, columnIndex }) / string--
header-cell-styleCallback method for the header cell's style. You can also use a fixed Object to set the same Style for all header cellsfunction({ row, column, rowIndex, columnIndex }) / object--
span-methodCalculation method for merging rows or columnsfunction({ row, column, rowIndex, columnIndex })--
first-column-indexThe column on which the tree expansion operation actsnumber-0
tree-propsConfiguration options for rendering nested dataobject-{ hasChildren: 'hasChildren', children: 'children' }
loadFunction for loading child node data. The second parameter of the function contains the node's level informationfunction(row, treeNode, resolve)--
colsColumn configuration, see the table belowarray--

cols

ParameterDescriptionTypeOptional ValuesDefault Value
columnKeyColumn key. This value needs to be set if dynamically switching table columns. Otherwise, the column width calculation will be incorrectstring
titleTable column titlestring
propProperty name of the table columnstring
showTooltipWhether to show a tooltip. This needs to be used in conjunction with the column's width valuebooleanfalse
tooltipPropsTooltip properties. Refer to the Popover component documentationobject
alignHorizontal alignmentstringleft/center/rightleft
widthColumn widthstring-
minWidthMinimum column widthstring-
maxWidthMaximum column widthstring-
fixedFixes the columnstring / objectleft / right / { position: string; distance: string; }-
slotNameColumn slot name. The default parameters are row, column, rowIndex, columnIndex. Please refer to the examplesstring--
headerSlotNameColumn header slot name. The default parameter is col. Please refer to the examplesstring--
sortableWhether the column is sortableboolean / stringtrue / false / 'ascending' / 'descending'-
filterColumn filter settingsobject{ slotName: string, placement: string, popperClass: string }--
expandExpand column settingsobject{ slotName: string, hideLabel: boolean }--
childrenInformation about child columns (for multi-level headers)array--
formatterUsed to format contentfunction(row, column, cellValue, rowIndex, columnIndex)--

Events

Event NameDescriptionCallback Parameter
row-clickTriggered when a row is clickedrow, rowIndex, event
cell-clickTriggered when a cell is clickedrow, col, rowIndex, colIndex, event
sort-changeTriggered when the sorting changesprop, sort
current-changeTriggered when the current row of the table changes. If you want to highlight the current row, enable the table's highlight-current-row attributecurrentRow, oldCurrentRow
expandTriggered when a row is expanded or collapsedexpanded, rowkey, slotName
tree-expandTriggered when a tree node is expanded or collapsedexpanded, row

Methods

Method NameDescriptionParameters
toggleExpandExpands/collapses a row. Since each row may have multiple expansions, you need to pass the slotName of the expansion you want to togglerowKey, slotName
toggleExpandTreeExpands/collapses a tree noderow
toggleColumnShows/hides a columnindex, show(show可选)
setCurrentRowUsed for single-selection tables. Sets a specific row as the selected row. If this method is called without parameters, it will cancel the selection of the currently highlighted rowrow
clearTooltipHides the tooltip-

Slots

NameDescription
emptyContent displayed when there is no data
unknownCustom content displayed when the table data is null or undefined
moreCustom content displayed during pull-down to load more
footFooter content of the table