最近在被安排去做前端开发,由于下拉框中的数据可能太多,滚动一个个翻着来查找影响效率,因此需要实现下拉框带有根据输入进行筛选的功能,由于本项目是用ant design
开发的,而antd
官网上针对下拉框Select
组件也有此功能的实现,具体代码案例如下:
<template> <a-select show-search placeholder="Select a person" option-filter-prop="children" style="width: 200px" :filter-option="filterOption" @focus="handleFocus" @blur="handleBlur" @change="handleChange" > <a-select-option value="jack"> Jack </a-select-option> <a-select-option value="lucy"> Lucy </a-select-option> <a-select-option value="tom"> Tom </a-select-option> </a-select> </template> <script> export default { methods: { handleChange(value) { console.log(`selected ${value}`); }, handleBlur() { console.log('blur'); }, handleFocus() { console.log('focus'); }, filterOption(input, option) { return ( option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 ); }, }, }; </script>
以上代码的重点就在于第3、5、7行和第35~39行,第3、5、7行使下拉框支持搜索功能,第35~39行通过filterOption
指定一个方法来实现筛选的规则,具体的效果实现也可直接去官网案例去体验下:访问官网案例
虽说官网上有案例,但在我们项目中使用却没有那么顺利,首先我们项目中的原先项目代码如下:
<a-select placeholder="全部" v-model:value="formState.llcsSysType" :getPopupContainer="(triggerNode) => triggerNode.parentNode"> <a-select-option v-model:value="item.roleCode" v-for="(item, index) in roleArr" :key="index"> {{ item.roleName }} </a-select-option> </a-select>
当我参考官网案例直接在a-select
标签上新增show-search
、option-filter-prop="children"
和filterOption
,具体如下(按理来说和官网一样应该没问题,但也可能会有问题,比如我这里就出了问题):
// 标签上新增showSearch、option-filter-prop="children"和filterOption <a-select placeholder="全部" v-model:value="formState.llcsSysType" :getPopupContainer="(triggerNode) => triggerNode.parentNode" show-search option-filter-prop="children" :filterOption="filterOption"> <a-select-option v-model:value="item.roleCode" v-for="(item, index) in roleArr" :key="index"> {{ item.roleName }} </a-select-option> </a-select> // filterOption定义成一个方法单独拿出来方便复用 methods: { filterOption(input, option) => { return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0 }; }
操作时发现始终提示Uncaught (in promise) TypeError: Cannot read property 'children' of undefine
:
经过调试发现,我打印了下option
发现它根本没有componentOptions
属性并展开看了一下,这时我猜想可能是antd版本的问题,而我想要的数据竟然还在children数组
的第一个元素的children
属性中:
那么问题就清晰了,根据实际结构,我此处完整的修改如下:
// 标签上新增showSearch和filterOption <a-select placeholder="全部" v-model:value="formState.llcsSysType" :getPopupContainer="(triggerNode) => triggerNode.parentNode" show-search option-filter-prop="children" :filterOption="filterOption"> <a-select-option v-model:value="item.roleCode" v-for="(item, index) in roleArr" :key="index"> {{ item.roleName }} </a-select-option> </a-select> // filterOption定义成一个方法单独拿出来方便复用 methods: { filterOption(input, option) => { // 重点在这 return option.children[0].children.toLowerCase().indexOf(input.toLowerCase()) >= 0 }; }
到此,问题解决,能实现和官方案例一样的效果,但是这也暴露出来一个问题,就是我们项目中的filterOption
中的参数option
和官网案例中的option
不是一个东西,从结构上看官网案例中的option
应该是我们项目里的option.children[0]
,这也可能是我们项目引用的时候和官网的有所差异导致的,也有网上说是因为我们option中的内容前后带有空格导致其变成了数组,但潘老师也未能证实,不过好在最终还是解决了,完美!