业务描述
在 element UI 中 el-select 组件可谓是非常方便,支持了对数据Item的检索label,但是因业务需要,需要针对数据Item 的其他字段进行检索,比如 item 的数据格式是这样的:
{value,label,pinyin,...}
现在需要对 value, pinyin,... 等字段进行检索, 我们应该怎么去支持它呢?
解决思路
我们先查看文档 了解el-select 组件的搜索描述
为
el-select添加filterable属性即可启用搜索功能。默认情况下,Select 会找出所有label属性包含输入值的选项。如果希望使用其他的搜索逻辑,可以通过传入一个filter-method来实现。filter-method为一个Function,它会在输入值发生变化时调用,参数为当前输入值。
从文档得知,为el-select 组件添加filterable 属性,就可以支持label 的搜索
要想实现我们上面的需求我们暂时可以想到有以下几种方式:
-
既然他支持
label的检索,那我们把需要检索的字段拼接进label,就自然而然的支持了。但是这样就存在另外一个问题,选项的lable出现了不该出现的数据显示,故此法应该行不通,暂不考虑。 -
检索条件传给后端开发,让后端去模糊匹配检索条件,返回结果集,成功将锅甩给后端开发,非常的 nice . 夸夸我这聪明的小脑瓜。
-
前端自己过滤option列表,找出结果集;这方式实现起来没什么难度。 使用 filter-method 方法,
filter-method为一个Function,它会在输入值发生变化时调用,参数为当前输入值;也能成功解决这个问题;但是在所有系统或组件中都能使用就不得重复写filter-method, 哪位了不重复写或者统一维护这个filter-method, 我们又可以将filter-method以 mixins 的方式抽出,采用局部按需混入,或全局混入。到这 里,我们也能成功的将问题完美解决。那么有没有一种一劳永逸或者更优的解决方案呢,让们不写filter-method不混入呢? -
思考片刻 他既然默认能对
label进行过滤检索,那肯定就能扩展别的字段进行检测,让我们翻一番他是怎么实现的,我们针对他的源码进行改造,让他能够自己适配其他字段的检索;这个主意甚好,让组件使用者无感知,不用维护太多的代码,甚至多业务系统可以做到统一,不由感叹 甚好 甚好 .....
那我们就来简单分析分析 el-option 组件他是怎么做的label 的过滤检索的
点击查看 option.vue 源码
经过我们的分析就是下面这个方法 (Line:137):
queryChange(query) {
this.visible = new RegExp(escapeRegexpString(query), 'i').test(this.currentLabel) || this.created;
if (!this.visible) {
this.select.filteredOptionsCount--;
}
}
<template>
<li
@mouseenter="hoverItem"
@click.stop="selectOptionClick"
class="el-select-dropdown__item"
v-show="visible"
:class="{
'selected': itemSelected,
'is-disabled': disabled || groupDisabled || limitReached,
'hover': hover
}">
<slot>
<span>{{ currentLabel }}</span>
</slot>
</li>
</template>
通过简单的分析: 我们发现 它是通过 v-show="visible" 来控制可选项的显示/隐藏的;就是说我们控制 visible 变量的值就可以了。那事情到这就变得简单了。
至此 我们只要重写 queryChange(query) 的实现就能够愉快的实现需求了。
参考代码
我们以 pinyin 字段为例进行简单的重写
import { Option } from 'element-ui';
import { escapeRegexpString } from 'element-ui/src/utils/util';
export default {
name: 'ElOption2',
inject: ['select'],
props: {
pinyin: {
type: String,
default: ''
}
},
computed: {
currentPinyin() {
return this.pinyin || (this.isObject ? '' : this.label)
}
},
methods: {
queryChange(query) {
const hasLabel = new RegExp(escapeRegexpString(query), 'i').test(this.currentLabel) || this.created;
// 新增代码...
let hasPinyin = true
if (this.currentPinyin){
hasPinyin = new RegExp(escapeRegexpString(query.toUpperCase()), 'i').test(this.currentPinyin) || this.created;
}
this.visible = hasLable || hasPinyin
if (!this.visible) {
this.select.filteredOptionsCount--
}
}
}
}
当然我们甚至还可以 设计 props 接受 整个Item 数据, 吧 Item 数据的所有属性值转换成一个 字符串,进行检索匹配;
那么我们在使用的时候,全局注册 el-option2 组件,或者覆盖 el-option
接着在项目中 使用的时候 传入 pinyin 属性 应有或者期望检索的字符串,即可完成对选项的检索;
甚至 如果系统中的业务比较统一, 我们甚至可以直接内置,不提供props 传参。
so . 到此就结束了....
下面请上我们今天的主角:有请小趴菜