Table 表格
通过配置生成表格,内置更适合中后台业务的功能。
TIP
某些属性在z-table内部被默认配置,例如:align 设置为 center
基础用法
配置column生成表格项。el-table相关属性直接在z-table组件上传入,el-table-column属性在column中配置。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
>
<template #expand="row">
{{ row.$index }}
</template>
</z-table>
</template>表格标题
配置title属性生成表格标题,支持字符串和函数类型,也可使用tableTitle插槽自定义。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
title="表格标题"
@refresh="getTableData"
/>
</template>操作按钮
column中配置操作项,type传入button,配置buttons数组。按钮属性直接在操作项中配置即可。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
{
type: 'button',
label: '操作',
buttons: [
{
type: 'primary',
link: true,
label: '编辑',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
label: '删除',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
],
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>操作按钮也支持动态属性,如:disabled等。传入一个方法,参数为当前行相关数据。
<!-- eslint-disable unused-imports/no-unused-vars -->
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
{
type: 'button',
label: '操作',
buttons: [
{
type: 'primary',
link: true,
label: '编辑',
disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => row.name === 'Steven',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
link: true,
label: '删除',
disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => row.age === 18,
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
],
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>操作项下拉
如需下拉,可以在buttons数组中配置type为dropdown,children中配置下拉选项
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
{
type: 'button',
label: '操作',
width: '200px',
buttons: [
{
type: 'primary',
link: true,
label: '编辑',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
link: true,
label: '删除',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
{
type: 'dropdown',
reference: '删除',
children: [
{
type: 'primary',
link: true,
label: '复制',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'copy')
},
},
{
type: 'danger',
link: true,
label: '操作',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'operate')
},
},
],
},
],
},
])
</script>
<template>
<z-table
:data="tableData"
:loading="loading"
:columns="columns"
/>
</template>reference字段配置下拉关联文案(默认为更多),支持函数和字符串类型。
支持配置el-dropdown和el-dropdown-item组件属性和方法。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
{
type: 'button',
label: '操作',
buttons: [
{
type: 'dropdown',
reference: '操作',
placement: 'top-start',
children: [
{
type: 'primary',
link: true,
label: '编辑',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'edit')
},
},
{
type: 'danger',
link: true,
label: '删除',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'delete')
},
},
],
},
{
type: 'dropdown',
reference: () => h('span', { style: { cursor: 'pointer' } }, '操作2'),
placement: 'top',
onVisibleChange: (visible: boolean) => {
console.log(visible, 'visible')
},
children: [
{
type: 'primary',
link: true,
label: '复制',
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'copy')
},
},
{
type: 'danger',
link: true,
label: '操作',
divided: true,
onClick: ({ row }: TableColumnScopeData<RowData>) => {
console.log(row, 'operate')
},
},
],
},
],
},
])
</script>
<template>
<z-table
:data="tableData"
:loading="loading"
:columns="columns"
/>
</template>分页
配置pagination,支持双向绑定,实现分页效果。layout默认配置为total, sizes, prev, pager, next, jumper,pageSizes默认配置为[100, 200, 300, 400, 500],支持自定义。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, prev, pager, next',
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>配置paginationLeft、paginationRight、paginationTop、paginationBottom插槽实现分页上下左右内容自定义。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { Pagination } from 'ideaz-element'
const loading = ref(false)
const tableData = ref<any>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, sizes, prev, pager, next, jumper',
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function mockApi(pagination: Pagination): Promise<{ result: { page: number, pageSize: number, total: number, list: any[] } }> {
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
:data="tableData"
:loading="loading"
:columns="columns"
@refresh="getTableData"
>
<template #paginationTop>
<div class="mb-4">
<el-card>paginationTop</el-card>
</div>
</template>
<template #paginationBottom>
<div class="mb-4">
<el-card>paginationBottom</el-card>
</div>
</template>
<template #paginationLeft>
<div class="mb-4">
<el-card>paginationLeft</el-card>
</div>
</template>
<template #paginationRight>
<div class="mb-4">
<el-card>paginationRight</el-card>
</div>
</template>
</z-table>
</template>前端分页
配置pagination的type为front,开启前端分页功能,totalData字段传入所有数据。
pageSize为0、pagination为false或pagination不传,分页不展示。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref([])
const totalData = ref<RowData[]>([])
const pagination = ref({
type: 'front',
page: 1,
pageSize: 2,
total: 0,
layout: 'total, sizes, prev, pager, next, jumper',
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'pagination front params')
return new Promise((resolve) => {
setTimeout(() => {
const data = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: data,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
totalData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
{{ tableData }}
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:loading="loading"
:columns="columns"
:total-data="totalData"
@refresh="getTableData"
/>
</template>分页位置
配置pagination的align字段,支持left、center、right,默认right。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, sizes, prev, pager, next, jumper',
align: 'center',
})
const alignOptions = [
{ label: 'left', value: 'left' },
{ label: 'center', value: 'center' },
{ label: 'right', value: 'right' },
]
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-radio v-model="pagination.align" :options="alignOptions" type="radio-button" />
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
/>
</template>列显隐
column中配置hide字段,支持函数或布尔值,函数返回布尔值,true表示隐藏,false表示显示。
<script lang="ts" setup>
import { ref } from 'vue'
const isHide = ref(false)
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
hide: () => isHide.value,
},
{
prop: 'gender',
label: '性别',
hide: true,
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function changeVisible() {
isHide.value = !isHide.value
}
</script>
<template>
<el-button @click="changeVisible">
点击修改列显隐
</el-button>
<z-table
:data="tableData"
:columns="columns"
/>
</template>列自定义
column中配置slot或render实现自定义列内容。
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
render: ({ row }: TableColumnScopeData<RowData>) => h('span', row.name),
},
{
prop: 'gender',
label: '性别',
slot: 'gender',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
>
<template #gender="{ row }">
<el-input :model-value="row.gender" />
</template>
</z-table>
</template>列类型
column中配置type实现表格列类型,支持expand、radio、selection、index。
支持自定义列组件,配置component字段,支持input、select、datepicker、switch、任意局部或全局注册组件。
TIP
type为radio或者需要跨页选中checkbox时,需要配合rowKey使用(默认id)。
TIP
component直接传入组件,请使用markRaw包裹,防止影响性能。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { markRaw, ref } from 'vue'
import { ElInput } from 'element-plus'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'expand',
},
{
type: 'index',
},
{
type: 'radio',
},
{
type: 'selection',
},
{
component: 'input',
prop: 'name',
label: '姓名',
onChange: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, column, $index, val)
},
onInput: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('input event', row, column, $index, val)
},
fieldProps: {
clearable: true,
},
},
{
component: 'select',
prop: 'gender',
label: '性别',
fieldProps: {
clearable: true,
},
onChange: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, column, $index, val)
},
},
{
prop: 'age',
label: '年龄',
component: markRaw(ElInput),
fieldProps: {
clearable: true,
},
onChange: ({ row, column, $index }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, column, $index, val)
},
onInput: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('input event', row, val)
},
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
</script>
<template>
<z-table v-model:data="tableData" :columns="columns" :options="options">
<template #expand>
<span>展开内容</span>
</template>
</z-table>
</template>动态属性
column自定义内容支持动态属性,disabled、placeholder等组件属性支持传入函数(函数属性暂不支持,如:ElInput组件的formatter属性),参数为当前行scope数据。
<!-- eslint-disable unused-imports/no-unused-vars -->
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { TableColumnScopeData } from 'ideaz-element'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref([
{
id: 1,
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: '姓名',
onChange: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, val)
},
onInput: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('input event', row, val)
},
fieldProps: {
clearable: true,
disabled: ({ row, column, $index }: TableColumnScopeData<RowData>) => {
return row.id === 1
},
},
},
{
component: 'select',
prop: 'gender',
label: '性别',
onChange: ({ row }: TableColumnScopeData<RowData>, val: string) => {
console.log('change event', row, val)
},
fieldProps: {
placeholder: ({ row, column, $index }: TableColumnScopeData<RowData>) => {
return `${row.name}性别${$index}`
},
clearable: true,
},
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
</script>
<template>
<z-table v-model:data="tableData" :columns="columns" :options="options" />
</template>表格头自定义
column中将label配置为带slot或Slot的字符串或配置为render函数实现自定义列表头。
<script lang="ts" setup>
import { h, ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: () => h('span', '自定义表头'),
},
{
prop: 'gender',
label: 'genderHeaderSlot',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
>
<template #genderHeaderSlot="scope">
<span>性别自定义表头{{ scope.$index }}</span>
</template>
</z-table>
</template>列提示
column中配置tooltip实现表头提示功能,支持函数和字符串。
<script lang="ts" setup>
import { h, ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
tooltip: () => h('span', '姓名提示'),
},
{
prop: 'gender',
label: '性别',
tooltip: '性别提示',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
/>
</template>相同项合并
表格属性配置mergeCells,支持单独配置行或列,支持配置字段。
interface mergeCells {
direction: 'row' | 'column' | 'both' // 合并方向:行、列、或两者都合并
props?: string[] // 需要合并的字段,不传则所有列都参与合并
}<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Steven',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'female',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
v-model:data="tableData"
:columns="columns"
:draggable="true"
:merge-cells="{
direction: 'both',
}"
border
/>
</template>工具栏
toolBar配置项,用于配置表格的工具栏。
toolBar值为false,不展示工具栏。
如果想配置某个功能不展示,配置toolBar下的四个字段refresh、density、fullScreen、setting为false即可。
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:tool-bar="false"
/>
</template>toolBar支持配置默认不选中,配置uncheck字段,值为column项的label。
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:tool-bar="{ uncheck: ['性别'], density: false, setting: false }"
/>
</template>toolBar支持排除某些表格项,配置exclude字段,值为column项的label。
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:tool-bar="{ exclude: ['性别'], fullScreen: false, refresh: false }"
/>
</template>toolBar上下左右内容支持自定义,通过toolBarTop、toolBarBottom、toolBarRight、toolBarLeft、tableTitle插槽配置。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
layout: 'total, prev, pager, next',
})
const columns = ref([
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
@refresh="getTableData"
>
<template #toolBarTop>
<div class="slot-demo">
toolBarTop
</div>
</template>
<template #toolBarBottom>
<div class="slot-demo">
toolBarBottom
</div>
</template>
<template #toolBarRight>
<div class="slot-demo">
toolBarRight
</div>
</template>
<template #toolBarLeft>
<div class="slot-demo">
toolBarLeft
</div>
</template>
<template #tableTitle>
<div class="slot-demo">
tableTitle
</div>
</template>
</z-table>
</template>
<style lang="scss">
.slot-demo {
padding: 10px;
border: 1px solid var(--el-card-border-color);
border-radius: var(--el-card-border-radius);
box-shadow: var(--el-box-shadow-light);
}
</style>数据拖拽
设置draggable为true,开启数据拖拽。
WARNING
必须配置row-key,否则会出现更新问题。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'sort',
label: '排序',
},
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function handleClick() {
console.log(tableData.value, 'handleClick')
}
function handleSortEnd(data: RowData[]) {
console.log(data, 'data')
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-table
v-model:data="tableData"
:columns="columns"
:draggable="true"
row-key="id"
@drag-sort-end="handleSortEnd"
/>
</template>支持设置slot或render自定义拖拽图标。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const tableData = ref<RowData[]>([
{
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'sort',
label: '排序',
},
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function handleSortEnd(data: RowData[]) {
console.log(data, 'data')
}
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:draggable="true"
@drag-sort-end="handleSortEnd"
>
<template #sort>
<el-icon size="16" class="cursor-pointer">
<i-setting />
</el-icon>
</template>
</z-table>
</template>可编辑表格
editable设置为true,开启表格编辑模式,该字段支持布尔值或对象类型,可编辑表格type默认为single。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: '姓名',
},
{
component: 'select',
prop: 'gender',
label: '性别',
},
{
component: 'input',
prop: 'age',
label: '年龄',
},
{
component: 'el-date-picker',
prop: 'time',
label: '出生日期',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
function handleClick() {
console.log(tableData.value, 'handleClick')
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-table
v-model:data="tableData"
:columns="columns"
:options="options"
:editable="true"
/>
</template>editable设置为type为multiple,开启多行编辑模式。
配置editable的maxLength,可以设置最大新增数量。配置editable的deleteConfirm为true,可开启删除二次确认。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: '姓名',
},
{
component: 'select',
prop: 'gender',
label: '性别',
},
{
component: 'input',
prop: 'age',
label: '年龄',
},
{
component: 'el-date-picker',
prop: 'time',
label: '出生日期',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
function handleClick() {
console.log(tableData.value, 'handleClick')
}
</script>
<template>
<el-button @click="handleClick">
click
</el-button>
<z-table
v-model:data="tableData"
:columns="columns"
:options="options"
:editable="{ type: 'multiple', deleteConfirm: true }"
/>
</template>配置editable的onSave、onDelete、onEdit、onCancel。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
import type { EditableTableEventParams } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
__isEdit?: boolean
}
const tableData = ref<RowData[]>([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: '姓名',
},
{
component: 'select',
prop: 'gender',
label: '性别',
},
{
component: 'input',
prop: 'age',
label: '年龄',
},
{
component: 'el-date-picker',
prop: 'time',
label: '出生日期',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
const editable = {
type: 'single',
maxLength: 5,
onCancel: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
console.log(row, $index, column, formRef, 'row onCancel')
},
onSave: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
console.log(row, $index, column, formRef, 'row onSave')
},
onDelete: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
console.log(row, $index, column, formRef, 'row onDelete')
},
onEdit: ({ row, $index, column, formRef }: EditableTableEventParams<RowData>) => {
row.__isEdit = true
console.log(row, $index, column, formRef, 'row onEdit')
},
}
</script>
<template>
<z-table
v-model:data="tableData"
:columns="columns"
:options="options"
:editable="editable"
/>
</template>支持自定义操作按钮。
<script lang="ts" setup>
import type { Ref } from 'vue'
import { ref } from 'vue'
import type { DefaultButtonOperation, TableColumnScopeData } from 'ideaz-element'
interface RowData {
name: string
gender: string
age: number
time: string
__isEdit: boolean
}
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: '姓名',
},
{
component: 'select',
prop: 'gender',
label: '性别',
},
{
component: 'input',
prop: 'age',
label: '年龄',
},
{
component: 'el-date-picker',
prop: 'time',
label: '出生日期',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
{
type: 'button',
label: '操作',
buttons: ({ renderEdit, renderCancel, renderDelete, renderSave }: DefaultButtonOperation, tableData: Ref<RowData[]>) => {
return [
{
type: 'primary',
link: true,
label: '复制',
hide: ({ row }: TableColumnScopeData<RowData>) => row.__isEdit,
onClick: ({ row }: TableColumnScopeData<RowData>) => {
tableData.value.push({ ...row })
},
},
renderEdit,
renderCancel,
renderDelete,
renderSave,
]
},
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
const editable = {
type: 'single',
maxLength: 5,
}
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:options="options"
:editable="editable"
/>
</template>吸顶
通过配置sticky属性的top、parent(会出现滚动条的DOM元素)和zIndex实现吸顶功能。 top默认为50px,zIndex默认为100。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'id',
label: 'id',
},
{
prop: 'name',
label: '姓名',
width: 300,
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
width: 300,
},
{
prop: 'time',
label: () => h('span', {}, 'customLabel'),
width: 300,
},
])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Mike',
gender: 'male',
age: 23,
time: '2020-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'female',
age: 16,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
id: 5,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 6,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
:sticky="{ parent: 'document' }"
@refresh="getTableData"
>
<template #expand="row">
{{ row.$index }}
</template>
</z-table>
</template>支持通过sticky.style自定义吸顶表格头样式。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { h, ref } from 'vue'
interface RowData {
name: string
gender: string
age: number
time: string
}
const loading = ref(false)
const tableData = ref<RowData[]>([])
const columns = ref([
{
prop: 'id',
label: 'id',
},
{
prop: 'name',
label: '姓名',
width: 300,
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
width: 300,
},
{
prop: 'time',
label: () => h('span', {}, 'customLabel'),
width: 300,
},
])
const pagination = ref({
page: 1,
pageSize: 2,
total: 0,
})
function mockApi(params: { page: number, pageSize: number }): Promise<{ result: { page: number, pageSize: number, total: number, list: RowData[] } }> {
console.log(params, 'params')
return new Promise((resolve) => {
setTimeout(() => {
const dataFirstPage = [
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Mike',
gender: 'male',
age: 23,
time: '2020-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'female',
age: 16,
time: '2012-01-01',
},
]
const dataSecondPage = [
{
id: 5,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 6,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
]
resolve({
result: {
page: 1,
pageSize: 10,
total: 4,
list: pagination.value.page === 1 ? dataFirstPage : dataSecondPage,
},
})
}, 100)
})
}
async function getTableData() {
loading.value = true
try {
const res = await mockApi({ ...pagination.value })
tableData.value = res.result.list
pagination.value.total = res.result.total
}
catch (error) {
console.log(error)
}
loading.value = false
}
getTableData()
</script>
<template>
<z-table
v-model:pagination="pagination"
v-model:data="tableData"
:columns="columns"
:loading="loading"
:sticky="{ parent: 'document', style: { border: '1px solid black' } }"
@refresh="getTableData"
>
<template #expand="row">
{{ row.$index }}
</template>
</z-table>
</template>水印
配置watermark,详情可参考el-watermark配置。
<script lang="ts" setup>
import { ref } from 'vue'
const tableData = ref([
{
name: 'Steven',
gender: '1',
age: 22,
time: '2020-01-01',
},
{
name: 'Helen',
gender: '1',
age: 12,
time: '2012-01-01',
},
{
name: 'Nancy',
gender: '2',
age: 18,
time: '2018-01-01',
},
{
name: 'Jack',
gender: '1',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
component: 'input',
prop: 'name',
label: '姓名',
},
{
component: 'select',
prop: 'gender',
label: '性别',
},
{
component: 'input',
prop: 'age',
label: '年龄',
},
{
component: 'el-date-picker',
prop: 'time',
label: '出生日期',
fieldProps: {
valueFormat: 'YYYY-MM-DD',
},
},
])
const options = {
gender: [
{ label: '男', value: '1' },
{ label: '女', value: '2' },
],
}
</script>
<template>
<z-table
:data="tableData"
:columns="columns"
:options="options"
watermark="表格水印"
/>
</template>表格方法
z-table的表格方法按照el-table使用即可。
<!-- eslint-disable no-console -->
<script lang="ts" setup>
import { ref } from 'vue'
interface RowData {
id: number
name: string
gender: string
age: number
time: string
}
const zTableRef = ref()
const radioData = ref({})
const selectionData = ref<RowData[]>([])
const tableData = ref<RowData[]>([
{
id: 1,
name: 'Steven',
gender: 'male',
age: 22,
time: '2020-01-01',
},
{
id: 2,
name: 'Helen',
gender: 'male',
age: 12,
time: '2012-01-01',
},
{
id: 3,
name: 'Nancy',
gender: 'female',
age: 18,
time: '2018-01-01',
},
{
id: 4,
name: 'Jack',
gender: 'male',
age: 28,
time: '2028-01-01',
},
])
const columns = ref([
{
type: 'radio',
},
{
type: 'selection',
},
{
prop: 'name',
label: '姓名',
},
{
prop: 'gender',
label: '性别',
},
{
prop: 'age',
label: '年龄',
},
{
prop: 'time',
label: '出生日期',
},
])
function handleRadioChange(row: RowData) {
radioData.value = row
console.log(row, 'radio data')
}
function handleSelectionChange(data: RowData[]) {
selectionData.value = data
console.log(data, 'selection data')
}
function handleClear() {
zTableRef.value.clearSelection()
}
</script>
<template>
<el-button @click="handleClear">
清空选中
</el-button>
<z-table
ref="zTableRef"
:data="tableData"
:columns="columns"
@radio-change="handleRadioChange"
@selection-change="handleSelectionChange"
/>
</template>z-table属性
| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| modelValue:data | 显示的数据,支持双向绑定 | array | — | — |
| modelValue:pagination | 分页配置,支持双向绑定 | object | — | — |
| loading | 表格加载 | boolean | — | — |
| title | 表格标题 | string / function | — | — |
| columns | 表格配置项 | array | — | — |
| toolBar | 工具栏配置 | object / boolean | — | — |
| editable | 可编辑表格配置 | object / boolean | — | — |
| options | 表格内部选项数据源 | object | — | — |
| watermark | 水印配置 | object(具体配置可查看el-watermark文档) | — | — |
| sticky | 表格头吸顶配置 | object | — | — |
| options | 表格内部选项数据源 | object | — | — |
| totalData | 表格所有数据(前端分页生效) | array | — | — |
| mergeCells | 表格相同项合并配置 | object | — | — |
| height | Table 的高度, 默认为自动高度。 如果 height 为 number 类型,单位 px;如果 height 为 string 类型,则这个高度会设置为 Table 的 style.height 的值,Table 的高度会受控于外部样式。 | string / number | — | — |
| max-height | Table 的最大高度。 合法的值为数字或者单位为 px 的高度。 | string / number | — | — |
| stripe | 是否为斑马纹 table | boolean | — | false |
| border | 是否带有纵向边框 | boolean | — | false |
| size | Table 的尺寸 | string | large / default /small | — |
| fit | 列的宽度是否自撑开 | boolean | — | true |
| show-header | 是否显示表头 | boolean | — | true |
| highlight-current-row | 是否要高亮当前行 | boolean | — | false |
| current-row-key | 当前行的 key,只写属性 | string / number | — | — |
| 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 | — | — |
| row-key | 行数据的 Key,用来优化 Table 的渲染; 在使用reserve-selection功能与显示树形数据时,该属性是必填的。 类型为 String 时,支持多层访问:user.info.id,但不支持 user.info[0].id,此种情况请使用 Function。 | function(row) / string | — | — |
| empty-text | 空数据时显示的文本内容, 也可以通过 #empty 设置 | string | — | No Data |
| default-expand-all | 是否默认展开所有行,当 Table 包含展开行存在或者为树形表格时有效 | boolean | — | false |
| expand-row-keys | 可以通过该属性设置 Table 目前的展开行,需要设置 row-key 属性才能使用,该属性为展开行的 keys 数组。 | array | — | — |
| default-sort | 默认的排序列的 prop 和顺序。 它的 prop 属性指定默认的排序的列,order 指定默认排序的顺序 | object | (order: 'ascending' 'descending') | 'descending') |
| tooltip-effect | 溢出的 tooltip 的 effect | string | dark / light | dark |
| tooltip-options | 溢出 tooltip 的选项,参见下述 tooltip 组件 | object | 请参考 tooltip | object |
| show-summary | 是否在表尾显示合计行 | boolean | — | false |
| sum-text | 显示摘要行第一列的文本 | string | — | Sum |
| summary-method | 自定义的合计计算方法 | function({ columns, data }) | — | — |
| span-method | 合并行或列的计算方法 | function({ row, column, rowIndex, columnIndex }) | — | — |
| select-on-indeterminate | 在多选表格中,当仅有部分行被选中时,点击表头的多选框时的行为。 若为 true,则选中所有行;若为 false,则取消选择所有行 | boolean | — | true |
| indent | 展示树形数据时,树节点的缩进 | number | — | 16 |
| lazy | 是否懒加载子节点数据 | boolean | — | — |
| load | 加载子节点数据的函数,lazy 为 true 时生效 | function(row, treeNode, resolve) | — | — |
| tree-props | 渲染嵌套数据的配置选项 | object | — | { hasChildren: 'hasChildren', children: 'children' } |
| table-layout | 设置表格单元、行和列的布局方式 | string | fixed / auto | fixed |
| scrollbar-always-on | 总是显示滚动条 | boolean | — | false |
| show-overflow-tooltip | 是否隐藏额外内容并在单元格悬停时使用 Tooltip 显示它们。这将影响全部列的展示。 | boolean \ | object | 参考 tooltip-options |
| flexible | 确保主轴的最小尺寸,以便不超过内容 | boolean | — | false |
| virtual | 虚拟滚动配置,支持高性能大数据渲染 | boolean / object | 详见虚拟表格文档 | false |
z-table事件
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| refresh | 翻页时触发的事件 | pagination |
| radio-change | 当用户手动勾选数据行的 Radio 时触发的事件 | row |
| select | 当用户手动勾选数据行的 Checkbox 时触发的事件 | selection, row |
| select-all | 当用户手动勾选全选 Checkbox 时触发的事件 | selection |
| selection-change | 当选择项发生变化时会触发该事件 | selection |
| cell-mouse-enter | 当单元格 hover 进入时会触发该事件 | row, column, cell, event |
| cell-mouse-leave | 当单元格 hover 退出时会触发该事件 | row, column, cell, event |
| cell-click | 当某个单元格被点击时会触发该事件 | row, column, cell, event |
| cell-dblclick | 当某个单元格被双击击时会触发该事件 | row, column, cell, event |
| cell-contextmenu | 当某个单元格被鼠标右键点击时会触发该事件 | row, column, cell, event |
| row-click | 当某一行被点击时会触发该事件 | row, column, event |
| row-contextmenu | 当某一行被鼠标右键点击时会触发该事件 | row, column, event |
| row-dblclick | 当某一行被双击时会触发该事件 | row, column, event |
| header-click | 当某一列的表头被点击时会触发该事件 | column, event |
| header-contextmenu | 当某一列的表头被鼠标右键点击时触发该事件 | column, event |
| sort-change | 当表格的排序条件发生变化的时候会触发该事件 | { column, prop, order } |
| filter-change | column 的 key, 如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件 | filters |
| current-change | 当表格的当前行发生变化的时候会触发该事件,如果要高亮当前行,请打开表格的 highlight-current-row 属性 | currentRow, oldCurrentRow |
| header-dragend | 当拖动表头改变了列的宽度的时候会触发该事件 | newWidth, oldWidth, column, event |
| expand-change | 当用户对某一行展开或者关闭的时候会触发该事件(展开行时,回调的第二个参数为 expandedRows;树形表格时第二参数为 expanded) | row, (expandedRows | expanded) |
z-table方法
| 方法名 | 说明 | 参数 |
|---|---|---|
| clearSelection | 用于多选表格,清空用户的选择 | — |
| getSelectionRows | 返回当前选中的行 | |
| toggleRowSelection | 用于多选表格,切换某一行的选中状态, 如果使用了第二个参数,则可直接设置这一行选中与否 | row, selected |
| toggleAllSelection | 用于多选表格,切换全选和全不选 | — |
| toggleRowExpansion | 用于可扩展的表格或树表格,如果某行被扩展,则切换。 使用第二个参数,您可以直接设置该行应该被扩展或折叠。 | row, expanded |
| setCurrentRow | 用于单选表格,设定某一行为选中行, 如果调用时不加参数,则会取消目前高亮行的选中状态。 | row |
| clearSort | 用于清空排序条件,数据会恢复成未排序的状态 | — |
| clearFilter | 传入由columnKey 组成的数组以清除指定列的过滤条件。 如果没有参数,清除所有过滤器 | columnKeys |
| doLayout | 对 Table 进行重新布局。 当表格可见性变化时,您可能需要调用此方法以获得正确的布局 | — |
| sort | 手动排序表格。 参数 prop 属性指定排序列,order 指定排序顺序。 | prop: string, order: string |
| scrollTo | 滚动到一组特定坐标 | (options: ScrollToOptions | number, yCoord?: number) |
| setScrollTop | 设置垂直滚动位置 | top |
| setScrollLeft | 设置水平滚动位置 | left |
z-table插槽
| 插槽名 | 说明 | 子标签 |
|---|---|---|
| append | 插入至表格最后一行之后的内容, 如果需要对表格的内容进行无限滚动操作,可能需要用到这个 slot。 若表格有合计行,该 slot 会位于合计行之上。 | — |
| empty | 当数据为空时自定义的内容 | — |
| tableTop | 顶部插槽 | — |
| tableBottom | 底部插槽 | — |
| toolBarTop | 工具栏顶部插槽 | — |
| toolBarBottom | 工具栏底部插槽 | — |
| toolBarRight | 工具栏右部插槽 | — |
| toolBarLeft | 工具栏左侧左部插槽 | — |
| tableTitle | 表格标题插槽 | — |
| paginationTop | 分页顶部插槽 | — |
| paginationBottom | 分页底部插槽 | — |
| paginationLeft | 分页左侧插槽 | — |
| paginationRight | 分页右侧插槽 | — |
| footer | 虚拟表格底部插槽,仅虚拟滚动模式下可用 | — |
columns属性
| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| type | 对应列的类型。 | string | selection / index / expand/ radio / button | |
| component | 列组件型。 | string | input / select / checkbox / radio / 任意局部或全局注册组件 | — |
| index | 如果设置了 type=index,可以通过传递 index 属性来自定义索引 | number / function(index) | — | — |
| label | 显示的标题(建议配置) | string / (scope) => VNode | — | — |
| buttons | 按钮配置 | array | — | — |
| options | 选项组件数据源 | array | — | |
| tooltip | 列提示 | string / () => VNode | — | — |
| column-key | column 的 key, column 的 key, 如果需要使用 filter-change 事件,则需要此属性标识是哪个 column 的筛选条件 | string | — | — |
| prop | 字段名称 对应列内容的字段名, 也可以使用 property属性 | string | — | — |
| width | 对应列的宽度 | string / number | — | — |
| min-width | 对应列的最小宽度, 对应列的最小宽度, 与 width 的区别是 width 是固定的,min-width 会把剩余宽度按比例分配给设置了 min-width 的列 | string / number | — | — |
| fixed | 列是否固定在左侧或者右侧。 true 表示固定在左侧 | string / boolean | true / 'left' / 'right' | — |
| render-header | 列标题 Label 区域渲染使用的 Function | function({ column, $index }) | — | — |
| sortable | 对应列是否可以排序, 如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件 | boolean / string | custom | false |
| sort-method | 指定数据按照哪个属性进行排序,仅当sortable设置为true的时候有效。 应该如同 Array.sort 那样返回一个 Number | function(a, b) | — | — |
| sort-by | 指定数据按照哪个属性进行排序,仅当 sortable 设置为 true 且没有设置 sort-method 的时候有效。 如果 sort-by 为数组,则先按照第 1 个属性排序,如果第 1 个相等,再按照第 2 个排序,以此类推 | function(row, index) / string / array | — | — |
| sort-orders | 数据在排序时所使用排序策略的轮转顺序,仅当 sortable 为 true 时有效。 需传入一个数组,随着用户点击表头,该列依次按照数组中元素的顺序进行排序 | array | 数组中的元素需为以下三者之一:ascending 表示升序,descending 表示降序,null 表示还原为原始顺序 | ['ascending', 'descending', null] |
| resizable | 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) | boolean | — | true |
| formatter | 用来格式化内容 | function(row, column, cellValue, index) | — | — |
| show-overflow-tooltip | 当内容过长被隐藏时显示 tooltip | boolean \ | object | 参考表格的 tooltip-options |
| align | 对齐方式 | string | left / center / right | left |
| header-align | 表头对齐方式, 若不设置该项,则使用表格的对齐方式 | string | left / center / right | — |
| class-name | 列的 className | string | — | — |
| label-class-name | 当前列标题的自定义类名 | string | — | — |
| selectable | 仅对 type=selection 的列有效,类型为 Function,Function 的返回值用来决定这一行的 CheckBox 是否可以勾选 | function(row, index) | — | — |
| reserve-selection | 数据刷新后是否保留选项,仅对 type=selection 的列有效, 请注意, 需指定 row-key 来让这个功能生效。 | boolean | — | false |
| filters | 数据过滤的选项, 数组格式,数组中的元素需要有 text 和 value 属性。 数组中的每个元素都需要有 text 和 value 属性。 | Array<{text: string, value: string}> | — | — |
| filter-placement | 过滤弹出框的定位 | string | 与 Tooltip 的 placement 属性相同 | — |
| filter-multiple | 数据过滤的选项是否多选 | boolean | — | true |
| filter-method | 数据过滤使用的方法, 如果是多选的筛选项,对每一条数据会执行多次,任意一次返回 true 就会显示。 | function(value, row, column) | — | — |
| filtered-value | 选中的数据过滤项,如果需要自定义表头过滤的渲染方式,可能会需要此属性。 | array | — | — |
pagination属性
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 分页类型 | front / backbone | backbone |
| page | 当前页 | number | — |
| pageSize | 每页显示条目个数 | number | — |
| align | 分页位置 | left / center / right | right |
| small | 是否使用小型分页样式 | boolean | true |
| background | 是否为分页按钮添加背景色 | boolean | false |
| total | 总条目数 | number | — |
| page-count | 总页数, total 和 page-count 设置任意一个就可以达到显示页码的功能;如果要支持 page-sizes 的更改,则需要使用 total 属性 | number | — |
| pager-count | 设置最大页码按钮数。 页码按钮的数量,当总页数超过该值时会折叠 | number | 7 |
| layout | 组件布局,子组件名用逗号分隔 | string | prev, pager, next, jumper, ->, total |
| page-sizes | 每页显示个数选择器的选项设置 | object | [10, 20, 30, 40, 50, 100] |
| popper-class | 每页显示个数选择器的下拉框类名 | string | '' |
| prev-text | 替代图标显示的上一页文字 | string | '' |
| prev-icon | 上一页的图标, 比 prev-text 优先级更高 | string / Component | ArrowLeft |
| next-text | 替代图标显示的下一页文字 | string | '' |
| next-icon | 下一页的图标, 比 next-text 优先级更低 | string / Component | ArrowRight |
| disabled | 是否禁用分页 | boolean | false |
| teleported | 是否将下拉菜单teleport至 body | boolean | true |
| hide-on-single-page | 只有一页时是否隐藏 | boolean | false |
editable属性
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 可编辑表格模式 | single / multiple | single |
| maxLength | 最大数量 | number | — |
| deleteConfirm | 删除二次确认 | boolean | false |
| onEdit | 编辑回调 | ({ row, index, column, formRef }) => void | — |
| onCancel | 取消回调 | ({ row, index, column, formRef }) => void | — |
| onSave | 保存回调 | ({ row, index, column, formRef }) => void | — |
| onDelete | 删除回调 | ({ row, index, column, formRef }) => void | — |
column中buttons属性
| 属性名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| type | 类型 | primary/ success'/ warning/ danger/ info / dropdown | — |
| label | 文案 | string | — |
| children | type为dropdown生效,下拉项 | array | — |
| hide | 按钮隐藏 | boolean / () => boolean | — |
| onClick | 点击事件 | ({ row, $index, column }) => void | — |
| plain | 是否为朴素按钮 | boolean | false |
| disabled | 按钮是否为禁用状态 | boolean / ({ row, $index, column }) => boolean | false |
| size | 尺寸 | default / large / small | — |
| plain | 是否为朴素按钮 | boolean | false |
| text | 是否为文字按钮 | boolean | false |
| bg | 是否显示文字按钮背景颜色 | boolean | false |
| link | 是否为链接按钮 | boolean | false |
| round | 是否为圆角按钮 | boolean | false |
| circle | 是否为圆形按钮 | boolean | false |
| loading | 是否为加载中状态 | boolean | false |
| loading-icon | 自定义加载中状态图标组件 | string / Component | Loading |
| icon | 图标组件 | string / Component | — |
| autofocus | 原生 autofocus 属性 | boolean | false |
| native-type | 原生 type 属性 | button / submit / reset | button |
| auto-insert-space | 自动在两个中文字符之间插入空格 | boolean | — |
| color | 自定义按钮颜色, 并自动计算 hover 和 active 触发后的颜色 | string | — |
| dark | dark 模式, 意味着自动设置 color 为 dark 模式的颜色 | boolean | false |
| tag | 自定义元素标签 | string / Component | button |
button类型为dropdown
| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| reference | 关联文案 | string / (scope) => VNode | — | 更多 |
| onCommand | 点击菜单项触发的事件回调 | (command) => void | — | — |
| type | 菜单按钮类型,同 Button 组件一样,仅在 split-button 为 true 的情况下有效。 | string | — | — |
| size | 菜单尺寸,在 split-button 为 true 的情况下也对触发按钮生效。 | string | large / default / small | default |
| max-height | 菜单最大高度 | string / number | — | — |
| split-button | 下拉触发元素呈现为按钮组 | boolean | — | false |
| disabled | 是否禁用 | boolean | — | false |
| placement | 菜单弹出位置 | string | top/top-start/top-end/bottom/bottom-start/bottom-end | bottom |
| trigger | 触发下拉的行为 | string | hover / click /contextmenu | hover |
| hide-on-click | 是否在点击菜单项后隐藏菜单 | boolean | — | true |
| show-timeout | 展开下拉菜单的延时,仅在 trigger 为 hover 时有效 | number | — | 250 |
| hide-timeout | 收起下拉菜单的延时(仅在 trigger 为 hover 时有效) | number | — | 150 |
| role | 下拉菜单的 ARIA 属性。 根据具体场景,您可能想要将此更改为“navigation” | string | — | 'menu' |
| tabindex | Dropdown 组件的 tabindex | number | — | 0 |
| popper-class | 自定义浮层类名 | string | — | — |
| popper-options | popper.js 参数 | Object | 请参考 popper.js 文档 | {modifiers: [{name: 'computeStyles',options: {gpuAcceleration: false}}]} |
| teleported | 是否将下拉列表插入至 body 元素 | boolean | — | true |
button类型为dropdown的children下拉项属性
| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| disabled | 是否禁用 | boolean / ({ row, $index, column }) => boolean | — | false |
| onClick | 下拉项点击 | ({ row, $index, column }) => void | — | — |
| divided | 是否显示分隔符 | boolean | — | false |
| icon | 自定义图标 | string / Component | — | — |
toolBar属性
| 属性名 | 说明 | 类型 | 可选值 | 默认值 |
|---|---|---|---|---|
| exclude | 不显示在工具栏的表格项 label 集合 | array | — | — |
| unCheck | 默认不选中的 label 集合 | array | — | — |
| refresh | 刷新功能是否展示 | boolean | — | true |
| density | 密度功能是否展示 | boolean | — | true |
| fullScreen | 全屏功能是否展示 | boolean | — | true |
| setting | 列配置功能是否展示 | boolean | — | true |