Vxe UI vue vxe-table 常用功能使用分享
表格需求
如果你需要的是一个能够渲染简单场景的表格,那么使用主流 UI 库就够了,例如element ui自带的表格等。
如果你需要是一个能同时满足简单场景以及各类复杂场景、大数量的全功能表格,那么推荐 vxe-table 就是首选。无论是基础表格还是大数量表格,功能强大和渲染性能也很不错。
介绍
Vxe UI 是 vxe-table 配套的组件库,如果表格中需要用到一些组件,比如:弹框、抽屉、页签等,可以选择第三方的组件库,也可以使用配置的 UI 库,安装后就能直接使用。
// ...
import VxeUI from 'vxe-pc-ui'
import 'vxe-pc-ui/lib/style.css'
import VxeUITable from 'vxe-table'
import 'vxe-table/lib/style.css'
// ...
createApp(App).use(VxeUI).use(VxeUITable).mount('#app')
组件 table 和 grid 哪个好用
无需考虑,直接选 vxe-grid,vxe-grid 是 vxe-table 的配置式版本,table 能做的 grid 也能做,table不支持的,grid 也能支持。
单选
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
border: true,
height: 300,
rowConfig: {
isHover: true
},
radioConfig: {
labelField: 'name',
highlight: true
},
columns: [
{ type: 'radio', title: 'Name', width: 300 },
{ field: 'id', title: 'ID' },
{ field: 'age', title: 'Age' },
{ field: 'address', title: 'Address', showOverflow: true }
],
data: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 23, address: 'test abc' },
{ id: 10005, name: 'Test5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
]
})
</script>
多选
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
border: true,
height: 500,
rowConfig: {
isHover: true
},
checkboxConfig: {
labelField: 'name',
highlight: true
},
columns: [
{ type: 'checkbox', title: 'Name', width: 300 },
{ field: 'id', title: 'ID' },
{ field: 'age', title: 'Age' },
{ field: 'address', title: 'Address', showOverflow: true }
],
data: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 23, address: 'test abc' },
{ id: 10005, name: 'Test5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
]
})
</script>
表位合计
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
border: true,
showFooter: true,
height: 300,
columns: [
{ field: 'seq', type: 'seq', width: 70 },
{ field: 'name', title: 'Name' },
{ field: 'sex', title: 'Sex' },
{
field: 'num',
title: 'Num',
footerFormatter ({ itemValue }) {
return `¥${itemValue}元`
}
},
{ field: 'address', title: 'Address', showOverflow: true }
],
data: [
{ id: '10001', name: 'Test1', role: 'Develop', sex: 'Man', num: '28', address: 'test abc' },
{ id: '10002', name: 'Test2', role: 'Test', sex: 'Women', num: '22', address: 'Guangzhou' },
{ id: '10003', name: 'Test3', role: 'PM', sex: 'Man', num: '32', address: 'Shanghai' },
{ id: '10004', name: 'Test4', role: 'Designer', sex: 'Women', num: '24', address: 'Shanghai' },
{ id: '10005', name: 'Test5', role: 'Develop', sex: 'Man', num: '42', address: 'Guangzhou' },
{ id: '10006', name: 'Test6', role: 'Test', sex: 'Women', num: '39', address: 'Shanghai' },
{ id: '10007', name: 'Test7', role: 'Develop', sex: 'Man', num: '46', address: 'Shanghai' },
{ id: '10008', name: 'Test8', role: 'PM', sex: 'Women', num: '49', address: 'Guangzhou' }
],
footerData: [
{ seq: '合计', num: '282' }
]
})
</script>
右键菜单
支持表头、单元格、表尾等各种右键菜单的配置,功能太多,这里只简单说明一下基本使用
<template>
<div>
<vxe-grid ref="gridRef" v-bind="gridOptions" v-on="gridEvents"></vxe-grid>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { VxeUI } from 'vxe-table'
const gridRef = ref()
const gridOptions = reactive({
border: true,
showFooter: true,
rowConfig: {
isCurrent: true
},
columnConfig: {
resizable: true
},
columns: [
{ field: 'checkbox', type: 'checkbox', width: 50 },
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name' },
{ field: 'nickname', title: 'Nickname' },
{ field: 'age', title: 'Age' },
{ field: 'role', title: 'Role' },
{ field: 'address', title: 'Address', showOverflow: true }
],
data: [
{ id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
{ id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
{ id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 23, address: 'Shenzhen' },
{ id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' }
],
menuConfig: {
header: {
options: [
[
{ code: 'exportAll', name: '导出所有.csv', prefixIcon: 'vxe-icon-download', visible: true, disabled: false }
]
]
},
body: {
options: [
[
{ code: 'copy', name: '复制内容', prefixIcon: 'vxe-icon-copy', visible: true, disabled: false },
{ code: 'clear', name: '清除内容', visible: true, disabled: false },
{ code: 'reload', name: '刷新表格', visible: true, disabled: false }
],
[
{ code: 'myPrint', name: '打印', prefixIcon: 'vxe-icon-print', visible: true, disabled: false },
{ code: 'myExport', name: '导出.csv', prefixIcon: 'vxe-icon-download', visible: true, disabled: false }
]
]
},
footer: {
options: [
[
{ code: 'exportAll', name: '导出所有.csv', prefixIcon: 'vxe-icon-download', visible: true, disabled: false }
]
]
}
},
footerData: [
{ checkbox: '合计', age: 135 }
]
})
const gridEvents = {
cellMenu ({ row }) {
const $grid = gridRef.value
if ($grid) {
$grid.setCurrentRow(row)
}
},
menuClick ({ menu, row, column }) {
const $grid = gridRef.value
if ($grid) {
switch (menu.code) {
case 'copy':
if (row && column) {
if (VxeUI.clipboard.copy(row[column.field])) {
VxeUI.modal.message({ content: '已复制到剪贴板!', status: 'success' })
}
}
break
case 'clear':
$grid.clearData(row, column.field)
break
case 'myPrint':
$grid.print()
break
case 'myExport':
$grid.exportData()
break
}
}
}
}
</script>
个性化列设置
自定义列功能支持本地 localStorage 自动保存,服务端调用接口保存与恢复状态
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
border: true,
id: 'myCustomStorage',
toolbarConfig: {
custom: true
},
customConfig: {
storage: true
},
columns: [
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'role' },
{ field: 'sex', title: 'Sex' },
{ field: 'age', title: 'Age' },
{ field: 'address', title: 'address' }
],
data: [
{ id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' }
]
})
</script>
树表格
树表格支持多种结构,平级数组还是带父子层级的结构都能渲染,功能太多,这里只说其中一种方式
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const gridOptions = reactive({
border: true,
treeConfig: {
transform: true,
rowField: 'id',
parentField: 'parentId'
},
columns: [
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name', minWidth: 300, treeNode: true },
{ field: 'size', title: 'Size' },
{ field: 'type', title: 'Type' },
{ field: 'date', title: 'Date' }
],
data: [
{ id: 10000, parentId: null, name: 'Test1', type: 'mp3', size: 1024, date: '2020-08-01' },
{ id: 10050, parentId: null, name: 'Test2', type: 'mp4', size: 0, date: '2021-04-01' },
{ id: 24300, parentId: 10050, name: 'Test3', type: 'avi', size: 1024, date: '2020-03-01' },
{ id: 20045, parentId: 24300, name: 'Test4', type: 'html', size: 600, date: '2021-04-01' },
{ id: 10053, parentId: 24300, name: 'Test5', type: 'avi', size: 0, date: '2021-04-01' },
{ id: 24330, parentId: 10053, name: 'Test6', type: 'txt', size: 25, date: '2021-10-01' },
{ id: 21011, parentId: 10053, name: 'Test7', type: 'pdf', size: 512, date: '2020-01-01' },
{ id: 22200, parentId: 10053, name: 'Test8', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23666, parentId: null, name: 'Test9', type: 'xlsx', size: 2048, date: '2020-11-01' },
{ id: 23677, parentId: 23666, name: 'Test10', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23671, parentId: 23677, name: 'Test11', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23672, parentId: 23677, name: 'Test12', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23688, parentId: 23666, name: 'Test13', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23681, parentId: 23688, name: 'Test14', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23682, parentId: 23688, name: 'Test15', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 24555, parentId: null, name: 'Test16', type: 'avi', size: 224, date: '2020-10-01' },
{ id: 24566, parentId: 24555, name: 'Test17', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 24577, parentId: 24555, name: 'Test18', type: 'js', size: 1024, date: '2021-06-01' }
]
})
</script>
可编辑表格
<template>
<div>
<vxe-toolbar>
<template #buttons>
<vxe-button @click="insertEvent">新增</vxe-button>
<vxe-button @click="removeSelectEvent()">删除选中</vxe-button>
<vxe-button @click="validAllEvent">校验全表单元格</vxe-button>
<vxe-button @click="getSelectEvent">获取选中</vxe-button>
<vxe-button @click="getInsertEvent">获取新增</vxe-button>
<vxe-button @click="getRemoveEvent">获取删除</vxe-button>
<vxe-button @click="getUpdateEvent">获取修改</vxe-button>
</template>
</vxe-toolbar>
<vxe-table
border
show-overflow
keep-source
ref="tableRef"
:data="tableData"
:edit-rules="validRules"
:edit-config="{trigger: 'click', mode: 'row', showStatus: true}"
:valid-config="{msgMode: 'full'}">
<vxe-column type="checkbox" width="80"></vxe-column>
<vxe-column type="seq" width="80"></vxe-column>
<vxe-column field="name" title="Name" width="400" :edit-render="{}">
<template #edit="slotParams">
<vxe-input v-model="slotParams.row.name" type="text" @change="changeCellEvent(slotParams)"></vxe-input>
</template>
</vxe-column>
<vxe-column field="age" title="Age" width="200" :edit-render="{}">
<template #edit="slotParams">
<vxe-input v-model="slotParams.row.age" type="text" @change="changeCellEvent(slotParams)"></vxe-input>
</template>
</vxe-column>
<vxe-column field="sex" title="Sex" width="200" :edit-render="{}">
<template #edit="slotParams">
<vxe-input v-model="slotParams.row.sex" type="text" @change="changeCellEvent(slotParams)"></vxe-input>
</template>
</vxe-column>
<vxe-column field="date" title="Date" width="300" fixed="right" :edit-render="{}">
<template #edit="slotParams">
<vxe-input v-model="slotParams.row.date" type="date" @change="changeCellEvent(slotParams)"></vxe-input>
</template>
</vxe-column>
</vxe-table>
</div>
</template>
<script lang="jsx" setup>
import { ref } from 'vue'
import { VxeUI } from 'vxe-table'
const tableRef = ref()
const tableData = ref([
{ id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, address: 'test abc' },
{ id: 10002, name: '', role: 'Test', sex: '1', age: 22, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: '', age: 32, address: 'Shanghai' },
{ id: 10004, name: '', role: '', sex: '1', age: 23, address: 'test abc' },
{ id: 10005, name: 'Test5', role: '', sex: '', age: 30, address: 'Shanghai' },
{ id: 10006, name: 'Test6', role: 'Designer', sex: '1', age: 21, address: 'test abc' }
])
const validRules = ref({
name: [
{
validator ({ cellValue }) {
if (cellValue && !/^\w+$/.test(cellValue)) {
return new Error('名称格式不正确,必须字母或数字')
}
}
}
],
sex: [
{ required: true, message: '性别必须填写' }
],
age: [
{ type: 'number', min: 10, max: 100000, message: '输入 10 ~ 100000 范围' }
],
date: [
{ required: true, message: '日期必须填写' }
]
})
const validAllEvent = async () => {
const $table = tableRef.value
if ($table) {
const errMap = await $table.fullValidate(true)
if (errMap) {
const msgList = []
Object.values(errMap).forEach((errList) => {
errList.forEach((params) => {
const { rowIndex, column, rules } = params
rules.forEach((rule) => {
msgList.push(`第 ${rowIndex + 1} 行 ${column.title} 校验错误:${rule.message}`)
})
})
})
VxeUI.modal.message({
status: 'error',
slots: {
default () {
return (<div class="red" style="max-height: 400px;overflow: auto;">
{msgList.map(msg => <div>{msg}</div>)}
</div>)
}
}
})
} else {
VxeUI.modal.message({ status: 'success', message: '校验成功!' })
}
}
}
const changeCellEvent = (params) => {
const $table = tableRef.value
if ($table) {
$table.updateStatus(params)
}
}
const removeSelectEvent = () => {
const $table = tableRef.value
if ($table) {
$table.removeCheckboxRow()
}
}
const insertEvent = async () => {
const $table = tableRef.value
if ($table) {
const { row: newRow } = await $table.insert({})
// 插入一条数据并触发校验
const errMap = await $table.validate(newRow)
if (errMap) {
// 校验失败
}
}
}
const getSelectEvent = () => {
const $table = tableRef.value
if ($table) {
const selectRecords = $table.getCheckboxRecords()
VxeUI.modal.alert(selectRecords.length)
}
}
const getInsertEvent = () => {
const $table = tableRef.value
if ($table) {
const insertRecords = $table.getInsertRecords()
VxeUI.modal.alert(insertRecords.length)
}
}
const getRemoveEvent = () => {
const $table = tableRef.value
if ($table) {
const removeRecords = $table.getRemoveRecords()
VxeUI.modal.alert(removeRecords.length)
}
}
const getUpdateEvent = () => {
const $table = tableRef.value
if ($table) {
const updateRecords = $table.getUpdateRecords()
VxeUI.modal.alert(updateRecords.length)
}
}
</script>
内置分页查询
可以自己调用接口,也可以使用数据代理方式,配置一个查询方法就可以自动加载
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script setup>
import { reactive } from 'vue'
const list = [
{ id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 28, address: 'Shenzhen' },
{ id: 10002, name: 'Test2', nickname: 'T2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', nickname: 'T3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' },
{ id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 23, address: 'test abc' },
{ id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 30, address: 'Shanghai' },
{ id: 10006, name: 'Test6', nickname: 'T6', role: 'Designer', sex: 'Women', age: 21, address: 'Shenzhen' },
{ id: 10007, name: 'Test7', nickname: 'T7', role: 'Test', sex: 'Man', age: 29, address: 'Shenzhen' },
{ id: 10008, name: 'Test8', nickname: 'T8', role: 'Develop', sex: 'Man', age: 35, address: 'test abc' },
{ id: 10009, name: 'Test9', nickname: 'T9', role: 'Develop', sex: 'Man', age: 35, address: 'Shenzhen' },
{ id: 100010, name: 'Test10', nickname: 'T10', role: 'Develop', sex: 'Man', age: 35, address: 'Guangzhou' },
{ id: 100011, name: 'Test11', nickname: 'T11', role: 'Develop', sex: 'Man', age: 49, address: 'Guangzhou' },
{ id: 100012, name: 'Test12', nickname: 'T12', role: 'Develop', sex: 'Women', age: 45, address: 'Shanghai' },
{ id: 100013, name: 'Test13', nickname: 'T13', role: 'Test', sex: 'Women', age: 35, address: 'Guangzhou' },
{ id: 100014, name: 'Test14', nickname: 'T14', role: 'Test', sex: 'Man', age: 29, address: 'Shanghai' },
{ id: 100015, name: 'Test15', nickname: 'T15', role: 'Develop', sex: 'Man', age: 39, address: 'Guangzhou' },
{ id: 100016, name: 'Test16', nickname: 'T16', role: 'Test', sex: 'Women', age: 35, address: 'Guangzhou' },
{ id: 100017, name: 'Test17', nickname: 'T17', role: 'Test', sex: 'Man', age: 39, address: 'Shanghai' },
{ id: 100018, name: 'Test18', nickname: 'T18', role: 'Develop', sex: 'Man', age: 44, address: 'Guangzhou' },
{ id: 100019, name: 'Test19', nickname: 'T19', role: 'Develop', sex: 'Man', age: 39, address: 'Guangzhou' },
{ id: 100020, name: 'Test20', nickname: 'T20', role: 'Test', sex: 'Women', age: 35, address: 'Guangzhou' },
{ id: 100021, name: 'Test21', nickname: 'T21', role: 'Test', sex: 'Man', age: 39, address: 'Shanghai' },
{ id: 100022, name: 'Test22', nickname: 'T22', role: 'Develop', sex: 'Man', age: 44, address: 'Guangzhou' }
]
// 模拟接口
const findPageList = (pageSize, currentPage) => {
console.log(`调用查询接口 pageSize=${pageSize} currentPage=${currentPage}`)
return new Promise(resolve => {
setTimeout(() => {
resolve({
result: list.slice((currentPage - 1) * pageSize, currentPage * pageSize),
page: {
total: list.length
}
})
}, 100)
})
}
const gridOptions = reactive({
border: true,
height: 500,
pagerConfig: {},
proxyConfig: {
// props: {
// result: 'result', // 配置响应结果列表字段
// total: 'page.total' // 配置响应结果总页数字段
// },
ajax: {
query: ({ page }) => {
// 默认接收 Promise<{ result: [], page: { total: 100 } }>
return findPageList(page.pageSize, page.currentPage)
}
}
},
columns: [
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name' },
{ field: 'nickname', title: 'Nickname' },
{ field: 'role', title: 'Role' },
{ field: 'address', title: 'Address', showOverflow: true }
]
})
</script>
实现表格搜索
<template>
<div>
<p>
<vxe-input v-model="filterName" type="search" placeholder="试试全表搜索" @keyup="searchEvent"></vxe-input>
</p>
<vxe-table
border
class="mylist-table"
height="400"
:column-config="{useKey: true}"
:row-config="{useKey: true}"
:data="list">
<vxe-column type="seq" width="80"></vxe-column>
<vxe-column field="name" title="Name" type="html"></vxe-column>
<vxe-column field="role" title="Role" type="html"></vxe-column>
<vxe-column field="age" title="Age" type="html"></vxe-column>
<vxe-column field="address" title="Address" type="html"></vxe-column>
</vxe-table>
</div>
</template>
<script setup>
import { ref } from 'vue'
const filterName = ref('')
const list = ref([])
const tableData = ref([
{ id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, amount: 888, address: 'test abc' },
{ id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, amount: 666, address: 'Guangzhou' },
{ id: 10003, name: 'Test3', role: 'PM', sex: '1', age: 32, amount: 89, address: 'Shanghai' },
{ id: 10004, name: 'Test4', role: 'Designer', sex: '0', age: 23, amount: 1000, address: 'test abc' },
{ id: 10005, name: 'Test5', role: 'Develop', sex: '0', age: 30, amount: 999, address: 'Shanghai' },
{ id: 10006, name: 'Test6', role: 'Designer', sex: '0', age: 21, amount: 998, address: 'test abc' },
{ id: 10007, name: 'Test7', role: 'Test', sex: '1', age: 29, amount: 2000, address: 'test abc' },
{ id: 10008, name: 'Test8', role: 'Develop', sex: '1', age: 35, amount: 999, address: 'test abc' },
{ id: 10009, name: 'Test9', role: 'Test', sex: '1', age: 26, amount: 2000, address: 'test abc' },
{ id: 100010, name: 'Test10', role: 'Develop', sex: '1', age: 21, amount: 666, address: 'test abc' }
])
const searchEvent = () => {
const filterVal = String(filterName.value).trim().toLowerCase()
if (filterVal) {
const filterRE = new RegExp(filterVal, 'gi')
const searchProps = ['name', 'role', 'age', 'address']
const rest = tableData.value.filter(item => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1))
list.value = rest.map(row => {
const item = Object.assign({}, row)
searchProps.forEach(key => {
item[key] = String(item[key]).replace(filterRE, match => `<span class="keyword-highlight">${match}</span>`)
})
return item
})
} else {
list.value = tableData.value
}
}
searchEvent()
</script>
<style lang="scss" scoped>
.mylist-table {
::v-deep(.keyword-highlight) {
background-color: #FFFF00;
}
}
</style>
虚拟滚动,加载大量数据
<template>
<div>
<vxe-table
border
show-overflow
height="600"
:scroll-y="{enabled: true, gt: 0}"
:data="tableData">
<vxe-column type="seq" width="70"></vxe-column>
<vxe-column field="name" title="Name"></vxe-column>
<vxe-column field="role" title="Role"></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
</vxe-table>
</div>
</template>
<script setup>
import { ref } from 'vue'
const tableData = ref([])
// 模拟行数据
const loadList = (size = 200) => {
const dataList = []
for (let i = 0; i < size; i++) {
dataList.push({
id: 10000 + i,
name: 'Test' + i,
role: 'Developer',
sex: '男'
})
}
tableData.value = dataList
}
loadList(500)
</script>
窗口最大化与最小化
<template>
<div>
<vxe-button @click="openVerticalEvent">点击弹出</vxe-button>
</div>
</template>
<script setup>
import { VxeUI } from 'vxe-pc-ui'
let num = 1
const openVerticalEvent = () => {
VxeUI.modal.open({
title: `标题 ${num}`,
content: `我是第 ${num} 个,点击最小化纵向排列`,
mask: false,
lockView: false,
escClosable: true,
width: 600,
height: 400,
showZoom: true,
zoomConfig: {
minimizeLayout: 'vertical'
}
})
num++
}
</script>
分页打印功能
支持各种打印,如果数据导出 csv.、xlsx 等,则需要 安装扩展插件
<template>
<div>
<vxe-button @click="printEvent">分页打印表格</vxe-button>
<vxe-table
border
height="500"
ref="tableRef"
:data="tableData">
<vxe-column field="id" title="ID" width="60"></vxe-column>
<vxe-column field="name" title="Name"></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="address" title="Address"></vxe-column>
</vxe-table>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { VxeUI } from 'vxe-table'
import XEUtils from 'xe-utils'
const tableRef = ref()
const list = []
for (let i = 0; i < 100; i++) {
list.push({
id: 10001 + i,
name: 'Test1',
role: 'Develop',
sex: 'Man',
address: 'test abc'
})
}
const tableData = ref(list)
const printEvent = () => {
const $table = tableRef.value
if ($table) {
// 分割每页26条
Promise.all(XEUtils.chunk(tableData.value, 26).map(pageData => {
return $table.getPrintHtml({
data: pageData
}).then(({ html }) => {
return {
bodyHtml: html
}
})
})).then(pageBreaks => {
VxeUI.print({
title: '分页打印表格',
showPageNumber: true,
pageBreaks
})
})
}
}
</script>
单元格选取
单元格复制粘贴 Excel
支持从表格、WPC、Excel等互相复制粘贴、等
可视化设计器
支持自定义添加控件。自定义渲染等,功能太多,去看官网。。