vxe-table 是一個vue的表格元件,支援可編輯和虛擬滾動高效能表格,公司使用了幾年的表格,grid 渲染器擴充套件功能非常強大。
npm install vxe-pc-ui@4.3.2 vxe-table@4.9.3
// ...
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')
// ...
基礎使用
<template>
<div>
<vxe-table
:data="tableData">
<vxe-column type="seq" width="70"></vxe-column>
<vxe-column field="name" title="Name"></vxe-column>
<vxe-column field="sex" title="Sex"></vxe-column>
<vxe-column field="age" title="Age"></vxe-column>
</vxe-table>
</div>
</template>
<script>
export default {
data () {
const tableData = [
{ 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' }
]
return {
tableData
}
}
}
</script>
多選
單選
單元格合併
標題字首提示
凍結列
樹表格
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script>
export default {
data () {
const gridOptions = {
border: true,
treeConfig: {
rowField: 'id',
childrenField: 'children'
},
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, name: 'Test1', type: 'mp3', size: 1024, date: '2020-08-01' },
{
id: 10050,
name: 'Test2',
type: 'mp4',
size: 0,
date: '2021-04-01',
children: [
{
id: 24300,
name: 'Test3',
type: 'avi',
size: 1024,
date: '2020-03-01',
children: [
{ id: 20045, name: 'Test4', type: 'html', size: 600, date: '2021-04-01' },
{
id: 10053,
name: 'Test5',
type: 'avi',
size: 0,
date: '2021-04-01',
children: [
{ id: 24330, name: 'Test6', type: 'txt', size: 25, date: '2021-10-01' },
{ id: 21011, name: 'Test7', type: 'pdf', size: 512, date: '2020-01-01' },
{ id: 22200, name: 'Test8', type: 'js', size: 1024, date: '2021-06-01' }
]
}
]
}
]
},
{
id: 23666,
name: 'Test9',
type: 'xlsx',
size: 2048,
date: '2020-11-01',
children: [
{
id: 23677,
name: 'Test10',
type: 'js',
size: 1024,
date: '2021-06-01',
children: [
{ id: 23671, name: 'Test11', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23672, name: 'Test12', type: 'js', size: 1024, date: '2021-06-01' }
]
},
{
id: 23688,
name: 'Test13',
type: 'js',
size: 1024,
date: '2021-06-01',
children: [
{ id: 23681, name: 'Test14', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 23682, name: 'Test15', type: 'js', size: 1024, date: '2021-06-01' }
]
}
]
},
{
id: 24555,
name: 'Test16',
type: 'avi',
size: 224,
date: '2020-10-01',
children: [
{ id: 24566, name: 'Test17', type: 'js', size: 1024, date: '2021-06-01' },
{ id: 24577, name: 'Test18', type: 'js', size: 1024, date: '2021-06-01' }
]
}
]
}
return {
gridOptions
}
}
}
</script>
行與列拖拽調整順序
<template>
<div>
<vxe-button status="success" @click="resultEvent">獲取資料</vxe-button>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script>
export default {
data () {
const gridOptions = {
border: true,
columnConfig: {
useKey: true,
drag: true
},
rowConfig: {
useKey: true,
drag: true
},
columns: [
{ field: 'name', title: 'Name' },
{ field: 'role', title: 'Role', dragSort: true },
{ 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' }
]
}
return {
gridOptions
}
},
methods: {
resultEvent () {
const $grid = this.$refs.gridRef
if ($grid) {
const { visibleColumn } = $grid.getTableColumn()
console.log(visibleColumn)
}
}
}
}
</script>
可編輯表格
<template>
<div>
<vxe-grid v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script>
export default {
data () {
const gridOptions = {
border: true,
showOverflow: true,
editConfig: {
trigger: 'click',
mode: 'cell'
},
columns: [
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name', editRender: { name: 'input' } },
{ field: 'sex', title: 'Sex', editRender: { name: 'input' } },
{ field: 'age', title: 'Age', editRender: { name: 'input' } }
],
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' }
]
}
return {
gridOptions
}
}
}
</script>
資料校驗
<template>
<div>
<div>
<vxe-button @click="validEvent">校驗變動資料</vxe-button>
<vxe-button @click="fullValidEvent">校驗全量資料</vxe-button>
</div>
<vxe-grid ref="gridRef" v-bind="gridOptions"></vxe-grid>
</div>
</template>
<script>
import { VxeUI } from 'vxe-table'
export default {
data () {
const gridOptions = {
border: true,
showOverflow: true,
keepSource: true,
height: 300,
editConfig: {
trigger: 'click',
mode: 'row',
showStatus: true
},
editRules: {
role: [
{ required: true, message: '必須填寫' }
]
},
columns: [
{ type: 'checkbox', width: 60 },
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name', editRender: { name: 'VxeInput' } },
{ field: 'role', title: 'Role', editRender: { name: 'VxeInput' } },
{ field: 'sex', title: 'Sex', editRender: { name: 'VxeInput' } },
{ field: 'age', title: 'Age', editRender: { name: 'VxeInput' } },
{ field: 'date', title: 'Date', editRender: { name: 'VxeInput' } }
],
data: [
{ 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: 'Test4', role: 'Designer', sex: '', age: 23, address: 'test abc' },
{ id: 10005, name: '', role: '', sex: '1', age: 30, address: 'Shanghai' },
{ id: 10006, name: 'Test6', role: 'Designer', sex: '1', age: 21, address: 'test abc' }
]
}
return {
gridOptions
}
},
methods: {
async validEvent () {
const $grid = this.$refs.gridRef
if ($grid) {
const errMap = await $grid.validate()
if (errMap) {
VxeUI.modal.message({ status: 'error', content: '校驗不透過!' })
} else {
VxeUI.modal.message({ status: 'success', content: '校驗成功!' })
}
}
},
async fullValidEvent () {
const $grid = this.$refs.gridRef
if ($grid) {
const errMap = await $grid.validate(true)
if (errMap) {
VxeUI.modal.message({ status: 'error', content: '校驗不透過!' })
} else {
VxeUI.modal.message({ status: 'success', content: '校驗成功!' })
}
}
}
}
}
</script>
表格搜尋
<template>
<div>
<p>
<vxe-input v-model="filterName" type="search" placeholder="試試全表搜尋" @keyup="searchEvent"></vxe-input>
</p>
<vxe-grid v-bind="gridOptions" class="mylist-grid"></vxe-grid>
</div>
</template>
<script>
import XEUtils from 'xe-utils'
export default {
data () {
const tableAllData = [
{ 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 gridOptions = {
border: true,
height: 400,
columnConfig: {
useKey: true
},
rowConfig: {
useKey: true
},
columns: [
{ type: 'seq', width: 70 },
{ field: 'name', title: 'Name', type: 'html' },
{ field: 'sex', title: 'Sex', type: 'html' },
{ field: 'age', title: 'Age', type: 'html' },
{ field: 'address', title: 'Address', type: 'html' }
],
data: []
}
return {
gridOptions,
filterName: '',
tableAllData
}
},
methods: {
handleSearch () {
const filterVal = String(this.filterName).trim().toLowerCase()
if (filterVal) {
const filterRE = new RegExp(filterVal, 'gi')
const searchProps = ['name', 'role', 'age', 'address']
const rest = this.tableAllData.filter(item => searchProps.some(key => String(item[key]).toLowerCase().indexOf(filterVal) > -1))
this.gridOptions.data = rest.map(row => {
// 搜尋為克隆資料,不會汙染源資料
const item = XEUtils.clone(row)
searchProps.forEach(key => {
item[key] = String(item[key]).replace(filterRE, match => `<span class="keyword-highlight">${match}</span>`)
})
return item
})
} else {
this.gridOptions.data = this.tableAllData
}
},
// 節流函式,間隔500毫秒觸發搜尋
searchEvent: XEUtils.throttle(function () {
this.handleSearch()
}, 500, { trailing: true, leading: true })
},
created () {
this.handleSearch()
}
}
</script>
<style lang="scss" scoped>
.mylist-grid {
::v-deep(.keyword-highlight) {
background-color: #FFFF00;
}
}
</style>