基础使用
一个基于 vue 的 PC 端表格组件,支持增删改查、虚拟滚动、懒加载、快捷菜单、数据校验、树形结构、打印导出、表单渲染、数据分页、虚拟列表、模态窗口、自定义模板、渲染器、贼灵活的配置项、扩展接口等…
<vxe-grid v-bind="gridOptions1">
<template #toolbar_buttons>
<vxe-button @click="gridOptions1.align = 'left'">居左</vxe-button>
<vxe-button @click="gridOptions1.align = 'center'">居中</vxe-button>
<vxe-button @click="gridOptions1.align = 'right'">居右</vxe-button>
</template>
</vxe-grid>
export default {
data () {
return {
gridOptions1: {
border: true,
resizable: true,
showOverflow: true,
height: 300,
align: 'left',
toolbarConfig: {
slots: {
// 自定义工具栏模板
buttons: 'toolbar_buttons'
}
},
columns: [
{ type: 'seq', width: 50 },
{ field: 'name', title: 'Name' },
{ field: 'sex', title: 'Sex', showHeaderOverflow: true },
{ field: 'address', title: 'Address', showOverflow: true }
],
data: [
{ id: 10001, name: 'Test1', nickname: 'T1', role: 'Develop', sex: 'Man', age: 0, 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: 100, address: 'Shanghai' },
{ id: 10004, name: 'Test4', nickname: 'T4', role: 'Designer', sex: 'Women', age: 70, address: 'Shenzhen' },
{ id: 10005, name: 'Test5', nickname: 'T5', role: 'Develop', sex: 'Women', age: 10, address: 'Shanghai' },
{ id: 10006, name: 'Test6', nickname: 'T6', role: 'Designer', sex: 'Women', age: 90, address: 'Shenzhen' },
{ id: 10007, name: 'Test7', nickname: 'T7', role: 'Test', sex: 'Man', age: 5, address: 'Shenzhen' },
{ id: 10008, name: 'Test8', nickname: 'T8', role: 'Develop', sex: 'Man', age: 80, address: 'Shenzhen' }
]
}
}
}
}
<vxe-grid ref="xTable"
highlight-hover-row
highlight-current-row
:align="align"
:round="true"
:border="border"
:stripe="stripe"
:loading="loading"
:show-overflow="showOverflow"
:show-header="showHeader"
:show-footer="showFooter"
:toolbarConfig="toolbarConfig"
:export-config="exportConfig"
:edit-config="editConfig"
:filter-config="filterConfig"
:print-config="printConfig"
:footer-method="footerMethod"
:size="size"
:height="height"
:treeConfig="treeConfig"
:seq-config="{startIndex: (tablePage.pageIndex - 1) * tablePage.pageSize}"
:columns="columns"
:data="data"
:radio-config="radioConfig"
:checkbox-config="checkboxConfig"
:menu-config="tableMenu"
@edit-closed="editClosed"
@cell-click="rowClick"
@cell-dblclick="rowdblClick"
@menu-click="menuClick">
<!-- 自定义工具栏 -->
<template #toolbar_buttons>
<slot></slot>
</template>
<!-- 分页组件 -->
<template #pager>
<vxe-pager v-if="tablePage.showPage"
background
:layouts="['Sizes', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'FullJump', 'Total']"
:current-page.sync="tablePage.pageIndex"
:page-size.sync="tablePage.pageSize"
:page-sizes="[10,20,50,100,200]"
:total="tablePage.total"
@page-change="handlePageChange">
</vxe-pager>
</template>
</vxe-grid>
</template>
<script>
import '@/components/vxeTable/renderer.js'
export default {
name: 'Table',
props: {
loading: {
type: Boolean,
default: false
},
height: {
type: String || Number,
default: () => {
return 'auto'
}
},
stripe: {
type: Boolean,
default: true
},
border: {
type: String,
default: 'full'
},
align: {
type: String,
default: 'center'
},
showOverflow: {
type: String,
default: () => { }
},
showHeader: {
type: Boolean,
default: true
},
showFooter: {
type: Boolean,
default: false
},
toolbarConfig: {
type: Object,
default: () => { }
},
size: {
type: String,
default: () => { }
},
tablePage: {
type: Object,
default: () => {
return {
showPage: false,
pageIndex: 1,
pageSize: 10,
total: 0
}
}
},
columns: {
type: Array,
default: () => {
return []
}
},
data: {
type: Array,
default: () => {
return []
}
},
treeConfig: {
type: Object,
default: undefined
},
// 可编辑配置项
editConfig: {
type: Object,
default: () => {
return {
enabled: false,
trigger: 'click',
mode: 'row',
beforeEditMethod: true
}
}
},
// 复选框配置项
checkboxConfig: {
type: Object,
default: () => {
return { highlight: true, range: true, trigger: 'default' }
}
},
// 右键快捷菜单配置
tableMenu: {
type: Object,
default: () => {
return {}
}
},
// 表尾方法
footerMethod: {
type: Function,
default: () => {
return []
}
}
},
data() {
return {
// 导出配置项
exportConfig: {
// 默认选中类型
type: 'xlsx',
// 局部自定义类型
types: ['xlsx', 'csv'],
// 自定义数据量列表
modes: ['current', 'selected', 'all'],
filename: '',
sheetName: '',
isFooter: true,
isHeader: true,
isMerge: true,
isColgroup: true
},
filterConfig: {
remote: false
},
// 打印配置项
printConfig: {
mode: 'current',
modes: ['current'],
sheetName: '',
isHeader: true,
isColgroup: true,
isFooter: true
},
// 单选框配置项
radioConfig: {
highlight: true,
strict: false,
trigger: 'row'
}
}
},
methods: {
// 分页改变触发事件
handlePageChange({ currentPage, pageSize }) {
this.tablePage.pageIndex = currentPage
this.tablePage.pageSize = pageSize
this.$emit('pageChange', { pageIndex: currentPage, pageSize })
},
// 单元格点击事件
rowClick({ row, rowIndex, columnIndex, column }) {
Object.defineProperty(row, 'rowIndex', { // 给每一行添加不可枚举属性rowIndex来标识当前行
value: rowIndex,
writable: true,
enumerable: false
})
// 筛除多选时单击触发操作
if (!column.property) {
return
}
this.$emit('rowClick', { row, rowIndex, columnIndex })
},
// 单元格双击事件
rowdblClick({ row, rowIndex, column }) {
// 筛除多选时单击触发操作
if (!column.property) {
return
}
this.$emit('rowdblClick', { row, rowIndex })
},
// 右键点击单元格菜单
menuClick({ menu, row, column }) {
this.$emit('menuClick', { menu, row, column })
},
// 获取表格数据集(包括插入的临时数据)
getRecordset() {
return this.$refs.xTable.getRecordset()
},
// 获取当前选中的行数据(用于单选框)
getRadioRecord() {
return this.$refs.xTable.getRadioRecord()
},
// 删除复选框选中的行数据
removeCheckboxRow() {
return this.$refs.xTable.removeCheckboxRow()
},
// 获取当前已选中的行数据(用于复选框)
getCheckboxRecords() {
return this.$refs.xTable.getCheckboxRecords()
},
// 只对 edit-config 配置时有效,单元格编辑状态下被关闭时会触发该事件
editClosed(row, rowIndex, column) {
this.$emit('editClosed', row, rowIndex, column)
}
// 多选操作勾选某行
// setCheckboxRow(rows, checked) {
// if (rows.length === 0) { // 清除全部多选选择
// this.$refs.xTable.clearCheckboxRow()
// } else {
// this.$refs.xTable.setCheckboxRow(rows, checked)
// }
// }
// // 表格尾部
// sumNum(list, field) {
// let count = 0
// let num = 0
// list.forEach(item => {
// count += Number(item[field])
// num = count.toFixed(0)
// })
// return num
// },
// meanNum(list, field) {
// let count = 0
// list.forEach(item => {
// count += Number(item[field])
// })
// return (count / list.length).toFixed(2)
// },
// // 表格尾部总计
// footerMethod({ columns, data }) {
// // return this.footerData
// const sums = []
// columns.forEach((column, columnIndex) => {
// if (columnIndex === 0) {
// sums.push('总')
// } else {
// let sumCell = null
// switch (column.property) {
// case 'stCount':
// case 'Sales':
// case 'Trans':
// case 'lstCount':
// case 'lSales':
// case 'lTrans':
// sumCell = this.sumNum(data, column.property)
// break
// case 'AC':
// case 'lAC':
// sumCell = this.meanNum(data, column.property)
// break
// }
// sums.push(sumCell)
// }
// })
// // 返回一个二维数组的表尾合计
// return [sums]
// }
}
}
</script>
<style lang="less" scoped>
.my-menus {
background-color: #ffffff;
}
.my-menus .vxe-ctxmenu--link {
width: 300px;
}
.my-copy-item {
font-weight: 700;
font-style: oblique;
}
/deep/ .vxe-table--render-default .vxe-body--row.row--current {
background: #fff3e0;
}
/deep/ .vxe-toolbar {
padding: 0 15px;
.vxe-buttons--wrapper {
.vxe-button:not(.is--disabled):hover {
color: #82bdf8;
}
}
}
</style>
rederer.js
import SelcetFilter from './component/selcetFilter.vue'
import SelectContent from './component/selectContent.vue'
import DataFilter from './component/dataFilter.vue'
import Vue from 'vue'
Vue.component('SelcetFilter', SelcetFilter)
Vue.component('SelectContent', SelectContent)
Vue.component('DataFilter', DataFilter)
// 创建支持列内容的筛选渲染器
VXETable.renderer.add('SelcetFilter', {
// 不显示底部按钮,使用自定义的按钮
isFooter: false,
// 筛选模板
renderFilter(h, renderOpts, params) {
return [
<selcet-filter params={ params }></selcet-filter>
]
},
// 重置数据方法
filterResetMethod({ options }) {
options.forEach(option => {
option.data = { vals: [], sVal: '' }
})
},
// 筛选数据方法
filterMethod({ option, row, column }) {
const { vals } = option.data
const cellValue = row[column.field]
return vals.includes(cellValue)
}
})
// 创建支持列内容的筛选渲染器
VXETable.renderer.add('DataFilter', {
// 不显示底部按钮,使用自定义的按钮
isFooter: false,
// 筛选模板
renderFilter(h, renderOpts, params) {
return [
<data-filter params={ params }></data-filter>
]
},
// 重置数据方法
filterResetMethod({ options }) {
options.forEach(option => {
option.data = { vals: [], sVal: '' }
})
},
// 筛选数据方法
filterMethod({ option, row, column }) {
const { vals } = option.data
const cellValue = row[column.field]
return vals.includes(cellValue)
}
})
// 创建element-select下拉框的可编辑渲染器
VXETable.renderer.add('SelectContent', {
// 可编辑模板
renderEdit(h, renderOpts, params) {
return [
<select-content params={ params } ></select-content>
]
}
// 可编辑显示模板
// renderCell(h, renderOpts, params) {
// const {row, column} = params
// return [
// <span>{ row[column.field] }</span>
// ]
// }
})
dataFilter.vue
<div class="data-filter">
<el-date-picker clearable
v-model="value1"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="dataChage">
</el-date-picker>
</div>
</template>
<script>
export default {
name: 'DataFilter',
props: {
params: Object
},
inject: {
getTableData: { value: ' getTableData', default: null }
},
data() {
return {
value1: ''
}
},
methods: {
dataChage(val) {
console.log('%c [ val ]-31', 'font-size:13px; background:pink; color:#bf2c9f;', val)
}
}
}
</script>
<style scoped>
</style>