el-select 单选多选切换显示问题

4,078 阅读1分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

问题描述

这个是前段时间写多条件组合选择器发现的问题记录。
当对 el-select 由单选切换为多选时,多选框对应值改变,显示值不变的情况。如下图所示,当条件由单选切换为多选时,values 已清空,但时间依然显示的是 “星期一”

sle1.gif

分析

再看对应 el-select 组件, selected 值更新了 但 绑定显示的 selectedLabel 值没有更新。

1635652368.png
node_modules\element-ui\packages\select\src\select.vue

查看源码发现,selectedLabel 赋值只在 visible 监听和 setSelected 方法两个位置存在。进而查找 setSelected 方法,在 value 和 option 监听中调用。在已是多选的情况下尝试手动外层组件修改 value 值,setSelected 对应值依然保持不变,而显示多选 tag 的 setSelected 更新。
由源码的结构可知所谓多选,只是在原有的 el-input 下层显示对应的 tag 标签。而源码中确实没有对multiple 状态变更后的处理。在有值的状态下,改变 multiple 状态为多选后渲染会报错。推测可能是赋值与设置多选状态顺序不对导致的。

解决

两种解决方案:

  1. 直接给第二个 el-select 一个和是否多选相关的 key。
  2. 保证在单选状态下清空,再做多选初始化。

代码整理

        <el-form>
          <el-form-item label="条件: " class="rule-form-item">
            <el-select
              v-model="ruleItem.opreator"
              placeholder="请选择关联条件"
              @change="handleOpreatorChange"
              clearable
            >
              <el-option label="包含【单选】" :value="0"></el-option>
              <el-option label="等于【多选】" :value="1"></el-option>
            </el-select>
            <el-select
              v-model="ruleItem.values"
              :multiple="ruleItem.isMultiple"
              placeholder="请选择"
              clearable
              :key="ruleItem.opreator"
            >
              <!-- 方法一:
              el-select 加上 :key="ruleItem.opreator"
              更新整个 el-select -->
              <el-option
                v-for="item in ruleItem.options"
                :key="item"
                :label="item"
                :value="item"
                :multiple="true"
                
              >
                {{ item }}
              </el-option>
            </el-select>
          </el-form-item>
        </el-form>

export default {
  name: 'home',
  props: {},
  data() {
    return {
      ruleItem: {
        opreator: '',
        values: '',
        isMultiple: false,
        options: ['星期一', '星期二', '星期三', '星期四', '星期五']
      }
    }
  },
  computed: {},
  methods: {
    handleOpreatorChange(v) {
      if (v) {
        this.ruleItem.values = []
        this.ruleItem.isMultiple = !!v
        // 方法二 手动控制清空和改变多选状态的先后顺序
        // // let writeBack = this.ruleItem.values
        // this.ruleItem.values = ''
        // this.$nextTick(() => {
        //   this.ruleItem.isMultiple = true
        //   this.ruleItem.values = []
        //   // this.ruleItem.values = [writeBack]
        // })
      } else {
        this.ruleItem.values = ''
        this.ruleItem.isMultiple = !!v
      }
    }
  }
}

效果

sle2.gif
问题解决。