ElementUI2.x El-Select组件 处理使用远程查找时下拉箭头丢失问题
1、问题描述
elementui2.x版本使用el-select组件的remote-method远程查找时,发现下拉箭头丢失了,且当查找接口返回数据为空时,也不会展开下拉列表来显示暂无数据提示;
2、源码解析
官网使用示例:
<template>
<el-select
v-model="value"
multiple
filterable
remote
reserve-keyword
placeholder="请输入关键词"
:remote-method="remoteMethod"
:loading="loading">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
ElSelect组件源码问题解析:
1、查看源码发现是当props属性remote 和filterable 都为true时,导致计算属性iconClass返回的是空字符,所以下拉箭头不显示;
computed:{
...前面代码省略
iconClass() {
return this.remote && this.filterable ? '' : (this.visible ? 'arrow-up is-reverse' : 'arrow-up');
},
...后面代码省略
}
2、分析下面代码,发现下拉框只有在emptyText不为false且visible为true的情况下才会显示,且empty部分也必须emptyText有值才会显示,所以得去找emptyText;
<!-- 前面代码省略 -->
<transition
name="el-zoom-in-top"
@before-enter="handleMenuEnter"
@after-leave="doDestroy">
<el-select-menu
ref="popper"
:append-to-body="popperAppendToBody"
v-show="visible && emptyText !== false">
<el-scrollbar
tag="ul"
wrap-class="el-select-dropdown__wrap"
view-class="el-select-dropdown__list"
ref="scrollbar"
:class="{ 'is-empty': !allowCreate && query && filteredOptionsCount === 0 }"
v-show="options.length > 0 && !loading">
<el-option
:value="query"
created
v-if="showNewOption">
</el-option>
<slot></slot>
</el-scrollbar>
<template v-if="emptyText && (!allowCreate || loading || (allowCreate && options.length === 0 ))">
<slot name="empty" v-if="$slots.empty"></slot>
<p class="el-select-dropdown__empty" v-else>
{{ emptyText }}
</p>
</template>
</el-select-menu>
</transition>
</div>
</template>
3、找到emptyText代码分析发现,当remote为true,且query为空,options数组长度为0时,返回的是false,也就导致为什么当远程查询无数据时下拉框不显示的问题;
computed:{
...前面代码省略
emptyText() {
if (this.loading) {
return this.loadingText || this.t('el.select.loading');
} else {
if (this.remote && this.query === '' && this.options.length === 0) return false;
if (this.filterable && this.query && this.options.length > 0 && this.filteredOptionsCount === 0) {
return this.noMatchText || this.t('el.select.noMatch');
}
if (this.options.length === 0) {
return this.noDataText || this.t('el.select.noData');
}
}
return null;
},
...后面代码省略
}
3、解决办法(不想看源码解析可直接跳转到这里)
创建一个js文件(例如select.js),目录位置自己定,里面内容如下:
export default {
computed: {
iconClass() {
return this.visible ? 'arrow-up is-reverse' : 'arrow-up';
},
emptyText() {
if (this.loading) {
return this.loadingText || this.t('el.select.loading');
} else {
if (this.remote && this.query === '' && this.options.length === 0) {
return this.noMatchText || this.t('el.select.noMatch');
};
if (this.filterable && this.query && this.options.length > 0 && this.filteredOptionsCount === 0) {
return this.noMatchText || this.t('el.select.noMatch');
}
if (this.options.length === 0) {
return this.noDataText || this.t('el.select.noData');
}
}
return null;
},
}
}
在main.js中导入并使用对象结构合并到ElementUI.Select.computed上,注意这里必须要用结构来覆盖原有值,使用mixins混入是无效的(亲测),且结构最好在Vue.use(ElementUI, { size: 'mini' })前进行;
import Vue from 'vue'
import ElementUI from 'element-ui';
import '@/style/element-variables.scss'
import select_mixin from '@/components/elementui/mixins/select';
ElementUI.Select.computed = {...ElementUI.Select.computed, ...select_mixin.computed};
Vue.use(ElementUI, { size: 'mini' });