vxe-grid 全局自定义filter过滤器,支持字典过滤
一、vxe-table的全局筛选器filters的实现
官网例子:https://vxetable.cn/#/table/renderer/filter
进入之后:我们可以参照例子自行实现,也可以下载它的源码,进行调整
下载好后并解压,用vscode将解压后的文件打开。全局检索FilterInput,你工作中用的vxe-table多少版本的那就进多少版本的目录
点击进入,按照这个路劲找到对应文件夹
将filter相关的vue,复制到自己的项目中components文件夹下
将filter.tsx 到你的项目中去,常用的FilterInput和FilterContent组件,将其他的FilterExtend 和FilterComplex 相关的可以先注释掉。
打开filter.ts
这样就可以使用了,使用方式,按照官网的例子放到columns里即可,filters的结构不允许改变,他与filterRendes的组件是一一对应的
这里提供v4的相关源码代码:
FilterInput.vue
<template><div class="my-filter-input"><vxe-input type="text" v-model="demo1.option.data" placeholder="支持回车筛选" @keyup="keyupEvent" @input="changeOptionEvent"></vxe-input></div>
</template><script lang="ts">
import { defineComponent, PropType, reactive } from 'vue'
import { VxeInputEvents, VxeGlobalRendererHandles } from 'vxe-table'export default defineComponent({name: 'FilterInput',props: {params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>},setup (props) {const demo1 = reactive({option: null as any})const load = () => {const { params } = propsif (params) {const { column } = paramsconst option = column.filters[0]demo1.option = option}}const changeOptionEvent = () => {const { params } = propsconst { option } = demo1if (params && option) {const { $panel } = paramsconst checked = !!option.data$panel.changeOption(null, checked, option)}}const keyupEvent: VxeInputEvents.Keyup = ({ $event }) => {const { params } = propsif (params) {const { $panel } = paramsif ($event.keyCode === 13) {$panel.confirmFilter($event)}}}load()return {demo1,changeOptionEvent,keyupEvent}}
})
</script><style scoped>
.my-filter-input {padding: 10px;
}
</style>
FilterContent.vue
<template><div class="my-filter-content"><div class="my-fc-search"><div class="my-fc-search-top"><vxe-input v-model="demo1.option.data.sVal" placeholder="搜索"></vxe-input></div><div class="my-fc-search-content"><template v-if="demo1.valList.length"><ul class="my-fc-search-list my-fc-search-list-head"><li class="my-fc-search-item"><vxe-checkbox v-model="demo1.isAll" @change="changeAllEvent">全选</vxe-checkbox></li></ul><ul class="my-fc-search-list my-fc-search-list-body"><li class="my-fc-search-item" v-for="(item, sIndex) in demo1.valList" :key="sIndex"><vxe-checkbox v-model="item.checked">{{ item.value }}</vxe-checkbox></li></ul></template><template v-else><div class="my-fc-search-empty">无匹配项</div></template></div></div><div class="my-fc-footer"><vxe-button status="primary" @click="confirmFilterEvent">确认</vxe-button><vxe-button @click="resetFilterEvent">重置</vxe-button></div></div>
</template><script lang="ts">
import { defineComponent, PropType, reactive } from 'vue'
import { VxeGlobalRendererHandles } from 'vxe-table'
import XEUtils from 'xe-utils'export default defineComponent({name: 'FilterContent',props: {params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>},setup (props) {interface ColValItem {checked: boolean;value: string;}const demo1 = reactive({isAll: false,option: null as any,colValList: [] as ColValItem[],valList: [] as ColValItem[]})const load = () => {const { params } = propsif (params) {const { $table, column } = paramsconst { fullData } = $table.getTableData()const option = column.filters[0]const { vals } = option.dataconst colValList = Object.keys(XEUtils.groupBy(fullData, column.field)).map((val) => {return {checked: vals.includes(val),value: val} as ColValItem})demo1.option = optiondemo1.colValList = colValListdemo1.valList = colValList}}const searchEvent = () => {const { option, colValList } = demo1if (option) {demo1.valList = option.data.sVal ? colValList.filter((item) => item.value.indexOf(option.data.sVal) > -1) : colValList}}const changeAllEvent = () => {const { isAll } = demo1demo1.valList.forEach((item) => {item.checked = isAll})}const confirmFilterEvent = () => {const { params } = propsconst { option, valList } = demo1if (params && option) {const { data } = optionconst { $panel } = paramsdata.vals = valList.filter((item) => item.checked).map((item) => item.value)$panel.changeOption(null, true, option)$panel.confirmFilter()}}const resetFilterEvent = () => {const { params } = propsif (params) {const { $panel } = params$panel.resetFilter()}}load()return {demo1,searchEvent,changeAllEvent,confirmFilterEvent,resetFilterEvent}}
})
</script><style>
.my-filter-content {padding: 10px;user-select: none;
}
.my-filter-content .my-fc-search .my-fc-search-top {position: relative;padding: 5px 0;
}
.my-filter-content .my-fc-search .my-fc-search-top > input {border: 1px solid #ABABAB;padding: 0 20px 0 2px;width: 200px;height: 22px;line-height: 22px;
}
.my-filter-content .my-fc-search .my-fc-search-content {padding: 2px 10px;
}
.my-filter-content .my-fc-search-empty {text-align: center;padding: 20px 0;
}
.my-filter-content .my-fc-search-list {margin: 0;padding: 0;list-style: none;
}
.my-filter-content .my-fc-search-list-body {overflow: auto;height: 120px;
}
.my-filter-content .my-fc-search-list .my-fc-search-item {padding: 2px 0;display: block;
}
.my-filter-content .my-fc-footer {text-align: right;padding-top: 10px;
}
.my-filter-content .my-fc-footer button {padding: 0 15px;margin-left: 15px;
}
</style>
FilterExtend.vue
<template><div class="my-filter-excel"><div class="my-fe-top"><ul class="my-fe-menu-group"><li class="my-fe-menu-link"><span>升序</span></li><li class="my-fe-menu-link"><span>倒序</span></li></ul><ul class="my-fe-menu-group"><li class="my-fe-menu-link" @click="resetFilterEvent"><span>清除筛选</span></li><li class="my-fe-menu-link"><i class="vxe-icon-question-circle-fill my-fe-menu-link-left-icon"></i><span>筛选条件</span><i class="vxe-icon-question-circle-fill my-fe-menu-link-right-icon"></i><div class="my-fe-menu-child-list"><ul class="my-fe-child-menu-group-list" v-for="(cList, gIndex) in demo1.caseGroups" :key="gIndex"><li v-for="(cItem, cIndex) in cList" :key="cIndex" class="my-fe-child-menu-item" @click="childMenuClickEvent(cItem)"><span>{{ cItem.label }}</span></li></ul></div></li></ul></div><div class="my-fe-search"><div class="my-fe-search-top"><input v-model="demo1.option.data.sVal" placeholder="搜索"/><i class="vxe-icon-question-circle-fill my-fe-search-icon"></i></div><ul class="my-fe-search-list"><li class="my-fe-search-item" @click="sAllEvent"><i class="vxe-icon-question-circle-fill my-fe-search-item-icon"></i><span>(全选)</span></li><li class="my-fe-search-item" v-for="(val, sIndex) in searchList" :key="sIndex" @click="sItemEvent(val)"><i :class="[demo1.option.data.vals.indexOf(val) === -1 ? 'vxe-icon-question-circle-fill my-fe-search-item-icon' : 'vxe-icon-question-circle-fill my-fe-search-item-icon']"></i><span>{{ val }}</span></li></ul></div><div class="my-fe-footer"><vxe-button status="primary" @click="confirmFilterEvent">确认</vxe-button><vxe-button @click="resetFilterEvent">重置</vxe-button></div></div>
</template><script lang="ts">
import { defineComponent, PropType, reactive, computed } from 'vue'
import { VXETable, VxeGlobalRendererHandles } from 'vxe-table'
import XEUtils from 'xe-utils'export default defineComponent({name: 'FilterExtend',props: {params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>},setup (props) {interface CaseItem {label: string;value: string;}const demo1 = reactive({option: null as any,colValList: [] as string[],caseGroups: [[{ value: 'equal', label: '等于' },{ value: 'ne', label: '不等于' }],[{ value: 'greater', label: '大于' },{ value: 'ge', label: '大于或等于' },{ value: 'less', label: '小于' },{ value: 'le', label: '小于或等于' }]] as CaseItem[][]})const searchList = computed(() => {const { option, colValList } = demo1if (option) {return option.data.sVal ? colValList.filter(val => val.indexOf(option.data.sVal) > -1) : colValList}return []})const load = () => {const { params } = propsif (params) {const { $table, column } = paramsconst { fullData } = $table.getTableData()const option = column.filters[0]const colValList = Object.keys(XEUtils.groupBy(fullData, column.field))demo1.option = optiondemo1.colValList = colValList}}const sAllEvent = () => {const { option } = demo1if (option) {const { data } = optionif (data.vals.length > 0) {data.vals = []} else {data.vals = demo1.colValList}}}const sItemEvent = (val: string) => {const { option } = demo1if (option) {const { data } = optionconst vIndex = data.vals.indexOf(val)if (vIndex === -1) {data.vals.push(val)} else {data.vals.splice(vIndex, 1)}}}const confirmFilterEvent = () => {const { params } = propsconst { option } = demo1if (params && option) {const { data } = optionconst { $panel } = paramsdata.f1 = ''data.f2 = ''$panel.changeOption(null, true, option)$panel.confirmFilter()}}const resetFilterEvent = () => {const { params } = propsif (params) {const { $panel } = params$panel.resetFilter()}}const childMenuClickEvent = (cItem: CaseItem) => {VXETable.modal.alert({ content: cItem.label })}load()return {demo1,searchList,sAllEvent,sItemEvent,confirmFilterEvent,resetFilterEvent,childMenuClickEvent}}
})
</script><style>
.my-filter-excel {user-select: none;
}
.my-filter-excel .my-fe-top .my-fe-menu-group {position: relative;margin: 0;padding: 0;
}
.my-filter-excel .my-fe-top .my-fe-menu-group:after {content: "";position: absolute;width: 190px;right: 0;bottom: 0;border-bottom: 1px solid #E2E4E7;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link {position: relative;padding: 4px 20px 4px 30px;cursor: pointer;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link:hover {background-color: #C5C5C5;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link-left-icon {position: absolute;left: 10px;top: 6px;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link-right-icon {position: absolute;right: 10px;top: 6px;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link:hover .my-fe-menu-child-list {display: block;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-menu-child-list {display: none;position: absolute;top: 0;right: -120px;width: 120px;background-color: #fff;border: 1px solid #DADCE0;box-shadow: 3px 3px 4px -2px rgba(0, 0, 0, 0.6);
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list {position: relative;padding: 0;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list:after {content: "";position: absolute;width: 90px;right: 0;bottom: 0;border-bottom: 1px solid #E2E4E7;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list > .my-fe-child-menu-item {position: relative;padding: 4px 20px 4px 30px;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}
.my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list > .my-fe-child-menu-item:hover {background-color: #C5C5C5;
}
.my-filter-excel .my-fe-search {padding: 0 10px 0 30px;
}
.my-filter-excel .my-fe-search .my-fe-search-top {position: relative;padding: 5px 0;
}
.my-filter-excel .my-fe-search .my-fe-search-top > input {border: 1px solid #ABABAB;padding: 0 20px 0 2px;width: 200px;height: 22px;line-height: 22px;
}
.my-filter-excel .my-fe-search .my-fe-search-top > .my-fe-search-icon {position: absolute;right: 5px;top: 10px;
}
.my-filter-excel .my-fe-search .my-fe-search-list {margin: 0;border: 1px solid #E2E4E7;padding: 2px 10px;overflow: auto;height: 140px;
}
.my-filter-excel .my-fe-search .my-fe-search-list .my-fe-search-item {cursor: pointer;padding: 2px 0;
}
.my-filter-excel .my-fe-search .my-fe-search-list .my-fe-search-item .my-fe-search-item-icon {width: 16px;
}
.my-filter-excel .my-fe-footer {text-align: right;padding: 10px 10px 10px 0;
}
.my-fe-popup .my-fe-popup-filter {padding-left: 30px;
}
.my-fe-popup .my-fe-popup-filter > .my-fe-popup-filter-select {width: 120px;
}
.my-fe-popup .my-fe-popup-filter > .my-fe-popup-filter-input {margin-left: 15px;width: 380px;
}
.my-fe-popup .my-fe-popup-describe {padding: 20px 0 10px 0;
}
.my-fe-popup .my-fe-popup-concat {padding-left: 50px;
}
.my-fe-popup .my-fe-popup-footer {text-align: right;
}
</style>
FilterComplex.vue
<template><div class="my-filter-complex"><div class="my-fc-type"><vxe-radio v-model="demo1.option.data.type" name="fType" label="has">包含</vxe-radio><vxe-radio v-model="demo1.option.data.type" name="fType" label="eq">等于</vxe-radio></div><div class="my-fc-name"><vxe-input v-model="demo1.option.data.name" type="text" placeholder="请输入名称" @input="changeOptionEvent()"></vxe-input></div><div class="my-fc-footer"><vxe-button status="primary" @click="confirmEvent">确认</vxe-button><vxe-button @click="resetEvent">重置</vxe-button></div></div>
</template><script lang="ts">
import { defineComponent, PropType, reactive } from 'vue'
import { VxeGlobalRendererHandles } from 'vxe-table'export default defineComponent({name: 'FilterComplex',props: {params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>},setup (props) {const demo1 = reactive({option: null as any})const load = () => {const { params } = propsif (params) {const { column } = paramsconst option = column.filters[0]demo1.option = option}}const changeOptionEvent = () => {const { params } = propsconst { option } = demo1if (params && option) {const { $panel } = paramsconst checked = !!option.data.name$panel.changeOption(null, checked, option)}}const confirmEvent = () => {const { params } = propsif (params) {const { $panel } = params$panel.confirmFilter()}}const resetEvent = () => {const { params } = propsif (params) {const { $panel } = params$panel.resetFilter()}}load()return {demo1,changeOptionEvent,confirmEvent,resetEvent}}
})
</script><style scoped>
.my-filter-complex {width: 260px;padding: 5px 15px 10px 15px;
}
.my-filter-complex .my-fc-type {padding: 8px 0;
}
.my-filter-complex .my-fc-footer {text-align: center;
}
</style>
filter.tsx
import { VXETable } from 'vxe-table'
import FilterInput from './components/FilterInput.vue'
import FilterContent from './components/FilterContent.vue'
import FilterComplex from './components/FilterComplex.vue'
import FilterExtend from './components/FilterExtend.vue'// 创建一个简单的输入框筛选
VXETable.renderer.add('FilterInput', {// 筛选模板renderFilter (renderOpts, params) {return <FilterInput params={ params }></FilterInput>},// 重置数据方法filterResetMethod (params) {const { options } = paramsoptions.forEach((option) => {option.data = ''})},// 重置筛选复原方法(当未点击确认时,该选项将被恢复为默认值)filterRecoverMethod ({ option }) {option.data = ''},// 筛选方法filterMethod (params) {const { option, row, column } = paramsconst { data } = optionconst cellValue = row[column.field]if (cellValue) {return cellValue.indexOf(data) > -1}return false}
})// 创建一个条件的渲染器
VXETable.renderer.add('FilterComplex', {// 不显示底部按钮,使用自定义的按钮showFilterFooter: false,// 筛选模板renderFilter (renderOpts, params) {return <FilterComplex params={ params }></FilterComplex>},// 重置数据方法filterResetMethod (params) {const { options } = paramsoptions.forEach((option) => {option.data = { type: 'has', name: '' }})},// 筛选数据方法filterMethod (params) {const { option, row, column } = paramsconst cellValue = row[column.field]const { name } = option.dataif (cellValue) {return cellValue.indexOf(name) > -1}return false}
})// 创建一个支持列内容的筛选
VXETable.renderer.add('FilterContent', {// 不显示底部按钮,使用自定义的按钮showFilterFooter: false,// 筛选模板renderFilter (renderOpts, params) {return <FilterContent params={ params }></FilterContent>},// 重置数据方法filterResetMethod (params) {const { options } = paramsoptions.forEach((option) => {option.data = { vals: [], sVal: '' }})},// 筛选数据方法filterMethod (params) {const { option, row, column } = paramsconst { vals } = option.dataconst cellValue = row[column.field]return vals.includes(cellValue)}
})// 创建一个复杂的筛选器
VXETable.renderer.add('FilterExtend', {// 不显示底部按钮,使用自定义的按钮showFilterFooter: false,// 筛选模板renderFilter (renderOpts, params) {return <FilterExtend params={ params }></FilterExtend>},// 重置数据方法filterResetMethod (params) {const { options } = paramsoptions.forEach((option) => {option.data = { vals: [], sVal: '', fMenu: '', f1Type: '', f1Val: '', fMode: 'and', f2Type: '', f2Val: '' }})},// 筛选数据方法filterMethod (params) {const { option, row, column } = paramsconst cellValue = row[column.field]const { vals, f1Type, f1Val } = option.dataif (cellValue) {if (f1Type) {return cellValue.indexOf(f1Val) > -1} else if (vals.length) {// 通过指定值筛选return vals.includes(cellValue)}}return false}
})
二、自行优化filters实现,支持字典的转换
通过上面的方式,已经实现了过滤器,但是多次使用,衍生出一个问题,就是如果我的列是个字典列,并且字典值的转换用的是columns内的solt,如FilterContent组件,它将会渲染的时字典的value列表,并非用户看到的中文列表,用户怎么知道你过滤器的看到的1,2,3和你的数据时对应的,或者时FilterInput 你输入的必须时字典code,不能是中文,否则将无法筛选出数据。
解决问题1: 在数据库查询数据时,根据该列关联字典表,将中文给转换过来,
解决问题2:前端查询数据后,在给表格赋值时将字典数据转换回来,这样有些麻烦,
解决问题3:优化筛选组件,使其支持字典的筛选。由于项目中只用到了FilterInput和FilterContent这里只提供这两个组件的优化。
1. 先说下在哪里做了调整
filtes的结构上做了些调整,data里都增加了字典的数据, filterContent 参数移除sval参数,同样在filterContent 组件内input筛选也将被移除,只保留多选列表进行筛选
FilterInput
“FilterContent.vue”,它与FilterInput不一样,需要面板打开时,就显示过滤列表
2. 调整后的代码
FilterContent.vue
<template><div class="my-filter-content"><div class="my-fc-search"><div class="my-fc-search-top"><!-- <vxe-inputv-model="demo1.option.data.sVal"placeholder="搜索"></vxe-input> --></div><div class="my-fc-search-content"><template v-if="demo1.valList.length"><ul class="my-fc-search-list my-fc-search-list-head"><li class="my-fc-search-item"><vxe-checkbox v-model="demo1.isAll" @change="changeAllEvent">全选</vxe-checkbox></li></ul><ul class="my-fc-search-list my-fc-search-list-body"><liv-for="(item, sIndex) in demo1.valList":key="sIndex"class="my-fc-search-item"><vxe-checkbox v-model="item.checked">{{item.label}}</vxe-checkbox></li></ul></template><template v-else><div class="my-fc-search-empty">无匹配项</div></template></div></div><div class="my-fc-footer"><vxe-button status="primary" @click="confirmFilterEvent">确认</vxe-button><vxe-button @click="resetFilterEvent">重置</vxe-button></div></div>
</template><script lang="ts">import { defineComponent, PropType, reactive } from 'vue';import { VxeGlobalRendererHandles } from 'vxe-table';import XEUtils from 'xe-utils';export default defineComponent({name: 'FilterContent',props: {params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>,},setup(props) {interface ColValItem {checked: boolean;value: string;label: string;}const demo1 = reactive({isAll: false,option: null as any,colValList: [] as ColValItem[],valList: [] as ColValItem[],});const load = () => {const { params } = props;if (params) {const { $table, column } = params;const { fullData } = $table.getTableData();const option: any = column.filters[0];const { vals } = option.data;/** 重置数据,解决bug:可能由于动态渲染columns,导致过滤面板勾选后点击确认按钮,过滤后无法更新表格数据,* 经过尝试,点击重置按钮,在进行过滤,可正常过滤,所以这里重置下data ;问题得以解决*/option.data = {vals: option.data.vals,// sVal: option.data.sVal,dict: option.data.dict ? option.data.dict : undefined,};if (option.data.dict && option.data.dict.length > 0) {const colValList = Object.keys(XEUtils.groupBy(fullData, column.field)).map((val) => {const value = option.data.dict.filter((item) => String(item.value) === String(val));let label = val;if (value.length > 0) {label = value[0].label;}return {checked: vals.includes(val),value: val,label,} as ColValItem;});demo1.option = option;demo1.colValList = colValList;demo1.valList = colValList;} else {const colValList = Object.keys(XEUtils.groupBy(fullData, column.field)).map((val) => {return {checked: vals.includes(val),value: val,label: val,} as ColValItem;});demo1.option = option;demo1.colValList = colValList;demo1.valList = colValList;}}};// const searchEvent = () => {// const { option, colValList } = demo1;// if (option) {// demo1.valList = option.data.sVal// ? colValList.filter(// (item) => item.value.indexOf(option.data.sVal) > -1// )// : colValList;// }// };const changeAllEvent = () => {const { isAll } = demo1;demo1.valList.forEach((item) => {item.checked = isAll;});};const confirmFilterEvent = () => {const { params } = props;const { option, valList } = demo1;if (params && option) {const { data } = option;const { $panel } = params;data.vals = valList.filter((item) => item.checked).map((item) => item.value);$panel.changeOption(null, true, option);$panel.confirmFilter();}};const resetFilterEvent = () => {const { params } = props;if (params) {const { $panel } = params;$panel.resetFilter();}};load();return {demo1,// searchEvent,changeAllEvent,confirmFilterEvent,resetFilterEvent,};},});
</script><style>.my-filter-content {padding: 10px;user-select: none;}.my-filter-content .my-fc-search .my-fc-search-top {position: relative;padding: 5px 0;}.my-filter-content .my-fc-search .my-fc-search-top > input {border: 1px solid #ababab;padding: 0 20px 0 2px;width: 200px;height: 22px;line-height: 22px;}.my-filter-content .my-fc-search .my-fc-search-content {padding: 2px 10px;}.my-filter-content .my-fc-search-empty {text-align: center;padding: 20px 0;}.my-filter-content .my-fc-search-list {margin: 0;padding: 0;list-style: none;}.my-filter-content .my-fc-search-list-body {overflow: auto;height: 120px;}.my-filter-content .my-fc-search-list .my-fc-search-item {padding: 2px 0;display: block;}.my-filter-content .my-fc-footer {text-align: right;padding-top: 10px;}.my-filter-content .my-fc-footer button {padding: 0 15px;margin-left: 15px;}
</style>
FilterInput.vue
<template><div class="my-filter-input"><vxe-inputv-model="demo1.option.data.sVal"type="text"placeholder="支持回车筛选"@keyup="keyupEvent"@input="changeOptionEvent"></vxe-input></div>
</template><script lang="ts">import { defineComponent, PropType, reactive } from 'vue';import { VxeInputEvents, VxeGlobalRendererHandles } from 'vxe-table';export default defineComponent({name: 'FilterInput',props: {params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>,},setup(props) {const demo1 = reactive({option: null as any,});const load = () => {const { params } = props;if (params) {const { column } = params;const option = column.filters[0];option.data = {sVal: option.data.sVal,dict: option.data.dict ? option.data.dict : undefined,};demo1.option = option;}};const changeOptionEvent = () => {const { params } = props;const { option } = demo1;if (params && option) {const { $panel } = params;const checked = !!option.data.sVal;$panel.changeOption(null, checked, option);}};const keyupEvent: VxeInputEvents.Keyup = ({ $event }) => {const { params } = props;if (params) {const { $panel } = params;if ($event.keyCode === 13) {$panel.confirmFilter($event);}}};load();return {demo1,changeOptionEvent,keyupEvent,};},});
</script><style scoped>.my-filter-input {padding: 10px;}
</style>
filter.tsx
import { VXETable } from 'vxe-table';
import FilterInput from '@/components/Filter/FilterInput.vue';
import FilterContent from '@/components/Filter/FilterContent.vue';
// import FilterComplex from './components/FilterComplex.vue'
// import FilterExtend from './components/FilterExtend.vue'// 创建一个简单的输入框筛选
VXETable.renderer.add('FilterInput', {// 筛选模板renderFilter: (renderOpts, params) => {return [<FilterInput params={ params }></FilterInput>];},// 重置数据方法filterResetMethod (params) {const { options } = params;options.forEach((option) => {option.data = {sVal: '',dict: option.data.dict ? option.data.dict : undefined,};});},// 重置筛选复原方法(当未点击确认时,该选项将被恢复为默认值)filterRecoverMethod ({ option }) {option.data = {sVal: '',dict: option.data.dict ? option.data.dict : undefined,};},// 筛选方法filterMethod (params) {const { option, row, column } = params;const { data } = option;if(data.dict && data.dict.length > 0) {const cellValue = row[column.field];const dictItem = data.dict.filter((item)=>item.label.indexOf(data.sVal) > -1).map((item) => item.value);if(dictItem.length > 0){return dictItem.indexOf(cellValue) > -1;}} else {const cellValue = row[column.field];if (cellValue) {return cellValue.indexOf(data.sVal) > -1;}}return false;},
});// // 创建一个条件的渲染器
// VXETable.renderer.add('FilterComplex', {
// // 不显示底部按钮,使用自定义的按钮
// showFilterFooter: false,
// // 筛选模板
// renderFilter (renderOpts, params) {
// return <FilterComplex params={ params }></FilterComplex>
// },
// // 重置数据方法
// filterResetMethod (params) {
// const { options } = params
// options.forEach((option) => {
// option.data = { type: 'has', name: '' }
// })
// },
// // 筛选数据方法
// filterMethod (params) {
// const { option, row, column } = params
// const cellValue = row[column.field]
// const { name } = option.data
// if (cellValue) {
// return cellValue.indexOf(name) > -1
// }
// return false
// }
// })// 创建一个支持列内容的筛选
VXETable.renderer.add('FilterContent', {// 不显示底部按钮,使用自定义的按钮showFilterFooter: false,// 筛选模板renderFilter (renderOpts, params) {return [<FilterContent params={ params }></FilterContent>];},// 重置数据方法filterResetMethod (params) {const { options } = params;options.forEach((option) => {option.data = { vals: [],dict: option.data.dict ? option.data.dict : undefined};});},// 筛选数据方法filterMethod (params) {const { option, row, column } = params;const { vals } = option.data;const cellValue = row[column.field];console.log(cellValue,vals.includes(cellValue))return vals.includes(cellValue);},
});// // 创建一个复杂的筛选器
// VXETable.renderer.add('FilterExtend', {
// // 不显示底部按钮,使用自定义的按钮
// showFilterFooter: false,
// // 筛选模板
// renderFilter (renderOpts, params) {
// return <FilterExtend params={ params }></FilterExtend>
// },
// // 重置数据方法
// filterResetMethod (params) {
// const { options } = params
// options.forEach((option) => {
// option.data = { vals: [], sVal: '', fMenu: '', f1Type: '', f1Val: '', fMode: 'and', f2Type: '', f2Val: '' }
// })
// },
// // 筛选数据方法
// filterMethod (params) {
// const { option, row, column } = params
// const cellValue = row[column.field]
// const { vals, f1Type, f1Val } = option.data
// if (cellValue) {
// if (f1Type) {
// return cellValue.indexOf(f1Val) > -1
// } else if (vals.length) {
// // 通过指定值筛选
// return vals.includes(cellValue)
// }
// }
// return false
// }
// })