elementui plus单选解决方案

.el-select__placeholder {
position: relative;
top: none;
transform: none;
}

elementui解决方案

最近我遇到了一个神奇的需求,客户要求对 el-select宽度 进行动态设置。

简单来说,就是我们公司有一些选择框,展示的内容像“中华人民共和国/广西壮族自治区/南宁市/西乡塘区”这么长,一不小心就会内容超长,显示不全。详情请看下面动图:

一般来说,想解决内容展示不全的问题,有几种方法。

第一种:给选择框加个tooltip效果,在鼠标悬浮时展示完整内容。

第二种:对用户选择label值进行切割,只展示最后一层内容。

但是我们的客户对这两种方案都不接受,要求选择的时候让select选择框的宽度动态增加。

有什么办法呢?客户就是上帝,必须满足,他们说什么就是什么,所以我们只能开动脑筋,动手解决。

我们打开控制台,来侦察一下el-select的结构,发现它是一个el-input--suffixdiv包裹着一个input,如下图所示。

内层input的宽度是100%,外层div的宽度是由这个内层input决定的。也就是说,内层input的宽度如果动态增加,外层div的宽度也会随之增加。那么问题来了,如何将内层input的宽度动态增加呢?

tips:

如果你对width的100%和auto有什么区别感兴趣,可以点击查看我之前的文章

探究 width:100%与width:auto区别

为了让我们的el-select宽度能够跟着内容走,我们可以在内层input同级别增加一个元素,内容就是用户选中的内容。内容越多,它就像一个胃口很大的小朋友,把外层div的宽度撑开。下面来看图示例 :

借助prefix

幸运的是,el-select本身有一个prefix的插槽选项,我们可以借助这个选项实现:

我们添加一个prefix的插槽,再把prefix的定位改成relative,并且把input的定位改成绝对定位absolute。最后将prefix的内容改成我们的选项内容。看看现在的效果:

 1<template>
 2  <div>
 3    <el-select class="autoWidth" v-model="value" placeholder="请选择">
 4      <template slot="prefix">
 5        {{optionLabel}}
 6      </template>
 7      <el-option
 8        v-for="item in options"
 9        :key="item.value"
10        :label="item.label"
11        :value="item.value"
12      >
13      </el-option>
14    </el-select>
15  </div>
16</template>
17
18<script>
19export default {
20  data() {
21    return {
22      options: [
23        {
24          value: "选项1",
25          label: "中华人民共和国/广东省/深圳市/福田区",
26        },
27        {
28          value: "选项2",
29          label: "中华人民共和国/广西壮族自治区/南宁市/西乡塘区",
30        },
31        {
32          value: "选项3",
33          label: "中华人民共和国/北京市",
34        },
35        {
36          value: "选项4",
37          label: "中华人民共和国/台湾省",
38        },
39        {
40          value: "选项5",
41          label: "中华人民共和国/香港特别行政区",
42        },
43      ],
44      value: "",
45    };
46  },
47  computed: {
48    optionLabel() {
49      return (this.options.find((item) => item.value === this.value) || {})
50        .label;
51    },
52  },
53};
54</script>
55<style lang="scss" scoped>
56
57::v-deep .autoWidth .el-input__prefix {
58  position: relative;
59}
60
61::v-deep .autoWidth input {
62  position: absolute;
63}
64</style>
65

现在el-select已经可以根据选项label的内容长短动态增加宽度了,但是我们还需要继续处理一下细节部分,将prefix的内容调整到和select框中的内容位置重叠,并且将它隐藏。看看现在的效果

 1::v-deep .autoWidth .el-input__prefix {
 2  position: relative;
 3  box-sizing: border-box;
 4  border: 1px solid #fff;
 5  padding: 0 30px;
 6  height: 40px;
 7  line-height: 40px;
 8  left: 0px;
 9  visibility: hidden;
10}

目前已经基本实现了效果了,还有最后一个问题,当用户没有选择内容的时候,select的宽度是“没有”的,如下图所示。

所以我们还得给他加上一个最小宽度

我们加上最小宽度以后,发现这个select的图标又没对齐,这是因为我们在重写.el-input__prefix样式的时候设置了padding: 0 30px,当用户没有选择内容的时候,select的图标应该是默认位置,我们需要继续调整代码,最后效果如下图所示:

最后附上完整代码:

 1<template>
 2  <div>
 3    <el-select
 4      class="autoWidth"
 5      :class="{ 'has-content': optionLabel }"
 6      v-model="value"
 7      placeholder="请选择"
 8      clearable
 9    >
10      <template slot="prefix">
11        {{ optionLabel }}
12      </template>
13      <el-option
14        v-for="item in options"
15        :key="item.value"
16        :label="item.label"
17        :value="item.value"
18      >
19      </el-option>
20    </el-select>
21  </div>
22</template>
23
24<script>
25export default {
26  data() {
27    return {
28      options: [
29        {
30          value: "选项1",
31          label: "中华人民共和国/广东省/深圳市/福田区",
32        },
33        {
34          value: "选项2",
35          label: "中华人民共和国/广西壮族自治区/南宁市/西乡塘区",
36        },
37        {
38          value: "选项3",
39          label: "中华人民共和国/北京市",
40        },
41        {
42          value: "选项4",
43          label: "中华人民共和国/台湾省",
44        },
45        {
46          value: "选项5",
47          label: "中华人民共和国/香港特别行政区",
48        },
49      ],
50      value: "",
51    };
52  },
53  computed: {
54    optionLabel() {
55      return (this.options.find((item) => item.value === this.value) || {})
56        .label;
57    },
58  },
59};
60</script>
61<style lang="scss" scoped>
62.autoWidth {
63  min-width: 180px;
64}
65::v-deep .autoWidth .el-input__prefix {
66  position: relative;
67  box-sizing: border-box;
68  border: 1px solid #fff;
69  padding: 0 30px;
70  height: 40px;
71  line-height: 40px;
72  left: 0px;
73  visibility: hidden;
74}
75
76::v-deep .autoWidth input {
77  position: absolute;
78}
79.autoWidth {
80  // 当.has-content存在时设置样式
81  &.has-content {
82    ::v-deep .el-input__suffix {
83      right: 5px;
84    }
85  }
86  // 当.has-content不存在时的默认或备选样式
87  &:not(.has-content) {
88    ::v-deep .el-input__suffix {
89      right: -55px;
90    }
91  }
92}
93</style>
94
个人笔记记录 2021 ~ 2025