1

好记性不如烂笔头,记录最近遇到的一个Select组件多隐藏属性模糊查询的需求,以及踩的一个微坑。

1. 实现简单的模糊查询

如果只是对Select组件Optionlable/value做模糊查询的话, 文档或者其他文章都讲过,可以使用下面的查询

<a-select
    v-model="search_obj.advertiser"
    style="width: 240px;"
    mode="multiple"
    :maxTagCount="1"                    
    :allowClear="true"
    :filterOption="filterOption"
>
    <a-select-option value="">
        全部
    </a-select-option>
    <a-select-option  v-for="(value, key) in show_advertiser_map" :value="value.advertiser_id">
        {{value.alias}}
    </a-select-option>
</a-select>
filterOption(input, option) {
      return (
        option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
      );
},

如下图所示:可以对option.componentOptions.children[0].text或者option.componentOptions.propsData.value做过滤,就能实现模糊查询的效果

2.实现隐藏属性的模糊查询

2.1正确思路:自定义attrs属性

<a-select-option
v-for="(value, key) in show_advertiser_map"
:value="value.advertiser_id"
:user_name="value.user_name"
>
    {{value.alias}}
</a-select-option>

a-select-option标签增加了一个user_name的属性

如图,就把问题转化为了情形1,使用filterOption函数过滤选项就好了,但是如果有很多个属性需要过滤呢?岂不是要添加很多个attrs属性,于是我尝试了更改思路

2.2 微坑思路:动态更改option数组show_advertiser_map

option是使用数组循环渲染出来的,那么监听input的变化,动态调整数组不就好了么?

<a-select
    v-model="search_obj.advertiser"
    style="width: 240px;"
    mode="multiple"
    :maxTagCount="1"                    
    :allowClear="true"
    @search="filterAdvertiser"
>
    <a-select-option value="">
        全部
    </a-select-option>
    <a-select-option  v-for="(value, key) in show_advertiser_map" :value="value.advertiser_id">
        {{value.alias}}
    </a-select-option>
</a-select>
if (val == '') {
    this.show_advertiser_map = this.advertiser_map[this.search_obj.game]
        return;
    }
    let arr = [];
    this.advertiser_map[this.search_obj.game].forEach((v) => {
        if (v.alias.indexOf(val) > -1
            || v.advertiser_id.indexOf(val) > -1
            || v.advertiser_name.indexOf(val) > -1
            || v.company_name.indexOf(val) > -1
            || v.platform == val
            || v.user_name.indexOf(val) > -1
        ) {
            arr.push(v)
        }
    })
this.show_advertiser_map = arr
console.log(this.show_advertiser_map)

我打印了最终原数组的值,发现是符合预期的,但是实际上select组件选项却依旧是对vlaue做了过滤,导致渲染出来的结果是不符合预期的。可是文档里面写的是filterOption接收bool/function,默认值是true,于是我尝试增加:

:filterOption="true"

依旧对vlaue做了过滤

再次尝试增加:

:filterOption="() => { return true; }"

符合预期!Done!

然后我尝试看Select组件对应的代码:

 filterOption: _vueTypes2['default'].oneOfType([_vueTypes2['default'].bool, _vueTypes2['default'].func]),

确实是接受bool/function

     var filterFn = this.$props.filterOption;
      if ((0, _propsUtil.hasProp)(this, 'filterOption')) {
        if (filterFn === true) {
          filterFn = defaultFilter.bind(this);
        }
      } else {
        filterFn = defaultFilter.bind(this);
      }

但是当是true,却有一个defaultFilter,ok, 离真相越来越近了,继续看defaultFilter是啥

export function defaultFilterFn(input, child) {
  var props = getPropsData(child);
  if (props.disabled) {
    return false;
  }
  var value = getPropValue(child, this.optionFilterProp);
  if (value.length && value[0].text) {
    value = value[0].text;
  } else {
    value = String(value);
  }
  return value.toLowerCase().indexOf(input.toLowerCase()) > -1;
}

哦豁,是对value进行过滤,怪不得

3.总结

  • 不指定filterOption, 是对选项的value进行过滤;
  • 普通指定filterOption, 可以对选项的lable/value进行过滤;
  • 直接动态调整Array, 需要指定filterOption返回恒真

tfzh
231 声望17 粉丝

code what u love & love what u code