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不为falsevisibletrue的情况下才会显示,且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代码分析发现,当remotetrue,且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' });

全篇完!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部