vxe-grid之筛选器
2026年4月5日 16:57
vxe-grid
vxe-table 的一部分, 能通过配置方式, 渲染出表格
普通筛选器与浮动筛选器
普通筛选器(非浮动的)
如下图所示(在列头下方, 单独占一个单元格)
![]()
浮动筛选器
如下图所示(漂浮在列头下方偏上的位置)
![]()
![]()
默认筛选器与自定义筛选器
默认筛选器
vxe-table 官方提供的筛选器(需配合 vxe-pc-ui 使用) 如: VxeInput
如果 vxe-pc-ui 已全量引入, 那直接在filterRender.name指定即可使用, filterRender.props 就是配置组件的props
{ title: '年龄', field: 'age', filterRender: { name: 'VxeInput', props: { clearable: true } } }
自定义筛选器
由用户根据业务需要, 自行定义的筛选器(可选择使用项目中实际使用的ui框架如: element-plus 或 ant-design-vue)
实现一个完整的自定义筛选器
实现一个完整的筛选器, 需要实现: 2个vue组件(普通筛选器和浮动筛选器), 以及1个渲染注入器(将你自定义的普通筛选器和浮动筛选器, 以自定义的名字注入到 vxe-table 中, 让 vxe-table 能够通过这个自定义的名字来渲染你的自定义筛选器)
普通筛选器
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { VxeGlobalRendererHandles, VxeTableDefines } from 'vxe-table';
defineOptions({ name: 'MyFilter' });
const props = defineProps<{
// 必须有该props, 用于接收这个组件所需要的自定义props
renderOpts: VxeGlobalRendererHandles.RenderTableFilterOptions
// 必须有该props, vxe-table会将表格实例, 列信息等通过该props注入进来
renderParams: VxeGlobalRendererHandles.RenderTableFilterParams<any>
}>()
// 过滤条件改变事件名称(自定义事件)
const FILTER_CHANGE_EVENT_NAME = 'filterChange'
// 获取自定义属性
const customProps = computed(()=>{
return props.renderOpts.props || {}
})
const curOption = ref<VxeTableDefines.FilterOption>()
const field = computed(() => {
const renderParams = props.renderParams
if (!renderParams) return ''
const column = renderParams.column
if (!column) return ''
return column.field
})
// 获取当前列的过滤条件初始值
function load() {
if (!field.value) return
curOption.value = props.renderParams.column.filters[0]
}
watch(field, load)
load()
function onClear() {
if (!curOption.value || !field.value) return
const { $table, column } = props.renderParams
// 清除过滤条件,并触发filterChange事件
$table.clearFilterByEvent(new Event(FILTER_CHANGE_EVENT_NAME), column)
}
function onConfirm(){
const option = curOption.value
if (!option || !field.value) return
const { $table, column } = props.renderParams
// checked 的值是用来决定列名旁边的过滤图标是否高亮显示
const checked = !!option.data
$table.updateFilterOptionStatus(option, checked)
// 保存过滤条件,并触发filterChange事件
$table.saveFilterPanelByEvent(new Event(FILTER_CHANGE_EVENT_NAME))
}
</script>
<template>
<div v-if="curOption" class="flex flex-col">
<div>
<el-input v-model="curOption.data" :placeholder="customProps.placeholder"></el-input>
</div>
<div class="flex flex-row">
<el-button class="w-1/2" type="primary" @click="onConfirm">确认</el-button>
<el-button class="w-1/2" @click="onClear">清除</el-button>
</div>
</div>
</template>
<style lang="scss" scoped></style>
onConfirm方法中提到的checked 的值是用来决定列名旁边的过滤图标是否高亮显示, 是指这个图标
![]()
浮动筛选器
<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { VxeGlobalRendererHandles, VxeTableDefines } from 'vxe-table';
defineOptions({ name: 'MyFilter' });
const props = defineProps<{
// 必须有该props, 用于接收这个组件所需要的自定义props
renderOpts: VxeGlobalRendererHandles.RenderTableFilterOptions
// 必须有该props, vxe-table会将表格实例, 列信息等通过该props注入进来
renderParams: VxeGlobalRendererHandles.RenderTableFilterParams<any>
}>()
// 过滤条件改变事件名称
const FILTER_CHANGE_EVENT_NAME = 'filterChange'
// 获取自定义属性
const customProps = computed(()=>{
return props.renderOpts.props || {}
})
const curOption = ref<VxeTableDefines.FilterOption>()
const field = computed(() => {
const renderParams = props.renderParams
if (!renderParams) return ''
const column = renderParams.column
if (!column) return ''
return column.field
})
// 获取当前列的过滤条件初始值
function load() {
if (!field.value) return
curOption.value = props.renderParams.column.filters[0]
}
watch(field, load)
load()
function onClear() {
if (!curOption.value || !field.value) return
const { $table, column } = props.renderParams
// 清除过滤条件,并触发filterChange事件
$table.clearFilterByEvent(new Event(FILTER_CHANGE_EVENT_NAME), column)
}
function onConfirm(){
const option = curOption.value
if (!option || !field.value) return
const { $table, column } = props.renderParams
// checked 的值是用来决定列名旁边的过滤图标是否高亮显示的
const checked = !!option.data
$table.updateFilterOptionStatus(option, checked)
// 保存过滤条件,并触发filterChange事件
$table.saveFilterPanelByEvent(new Event(FILTER_CHANGE_EVENT_NAME))
}
</script>
<template>
<div v-if="curOption" class="flex flex-col">
<div>
<el-input v-model="curOption.data" :placeholder="customProps.placeholder"></el-input>
</div>
<div class="flex flex-row">
<el-button class="w-1/2" type="primary" @click="onConfirm">确认</el-button>
<el-button class="w-1/2" @click="onClear">清除</el-button>
</div>
</div>
</template>
<style lang="scss" scoped></style>
渲染注入器
MyFilterRender.tsx
import { VxeUI, type VxeGlobalRendererHandles } from "vxe-table";
import MyFilter from "./MyFilter.vue";
import MyFilterFloating from "./MyFilterFloating.vue";
/**
* 注册自定义筛选渲染器
*/
VxeUI.renderer.add('MyFilter',{
/**
* 筛选容器是否显示尾部
*/
showTableFilterFooter:false,
/**
* 自定义筛选渲染内容
* @param renderOpts 渲染选项
* @param renderParams 渲染参数
* @returns
*/
renderTableFilter(renderOpts: VxeGlobalRendererHandles.RenderTableFilterOptions, renderParams: VxeGlobalRendererHandles.RenderTableFilterParams<any>){
return <MyFilter renderOpts={renderOpts} renderParams={renderParams} />
},
/**
* 自定义浮动筛选渲染内容
* @param renderOpts 渲染选项
* @param renderParams 渲染参数
* @returns
*/
renderTableFloatingFilter(renderOpts: VxeGlobalRendererHandles.RenderTableFloatingFilterOptions, renderParams: VxeGlobalRendererHandles.RenderTableFloatingFilterParams<any>){
return <MyFilterFloating renderOpts={renderOpts} renderParams={renderParams} />
}
})
使用自定义的筛选器
<!--
@file: Demo01.vue
@author: pan
-->
<script setup lang="ts">
import { ElMessage } from 'element-plus';
import { ref, useTemplateRef } from 'vue';
import { VxeGridDefines, VxeGridProps, VxeGridPropTypes } from 'vxe-table';
import JsonTableComm from './JsonTableComm.vue';
import { debounce } from 'lodash-unified';
// 注入自定义筛选渲染器
import './MyFilterRender.tsx'
const data = ref([
{
id: 1,
name: '张三',
age: 18,
sex: '男',
},
{
id: 2,
name: '李四',
age: 20,
sex: '女',
},
])
const columns = ref<VxeGridPropTypes.Columns>([
{
title: 'ID',
field: 'id',
},
{
title: '姓名',
field: 'name',
// 该项必须这么配置,里面的data就是过滤条件的初始值
filters: [
{ data: '' }
],
// MyFilter为自定义筛选器, 可以在props中配置自定义属性
filterRender: { name: 'MyFilter', props: { placeholder:'输入姓名查询...' } }
},
{
title: '年龄',
field: 'age',
filterRender: { name: 'VxeInput', props: { clearable: true } }
},
{
title: '性别',
field: 'sex',
},
])
/**
* 过滤条件改变时,会触发该事件(该事件由自定义筛选器MyFilter触发)
*/
function onFilterChange(params: VxeGridDefines.FilterChangeEventParams) {
console.log('filterChange', params.filterList, params)
ElMessage.info(`过滤条件改变为: ${JSON.stringify(params.filterList)}`)
}
</script>
<template>
<div class="vp-raw">
<div class="h-[300px]">
<vxe-grid ref="gridRef"
:data="data" :columns="columns" @filterChange="onFilterChange">
</vxe-grid>
</div>
</div>
</template>
<style lang="scss" scoped></style>