elementui plus单选解决方案
.el-select__placeholder {
position: relative;
top: none;
transform: none;
}
elementui解决方案
最近我遇到了一个神奇的需求,客户要求对 el-select 的 宽度 进行动态设置。
简单来说,就是我们公司有一些选择框,展示的内容像“中华人民共和国/广西壮族自治区/南宁市/西乡塘区”
这么长,一不小心就会内容超长,显示不全。详情请看下面动图:
一般来说,想解决内容展示不全的问题,有几种方法。
第一种:给选择框加个tooltip
效果,在鼠标悬浮时展示完整内容。
第二种:对用户选择label值进行切割,只展示最后一层内容。
但是我们的客户对这两种方案都不接受,要求选择的时候让select选择框的宽度动态增加。
有什么办法呢?客户就是上帝,必须满足,他们说什么就是什么,所以我们只能开动脑筋,动手解决。
我们打开控制台,来侦察一下el-select
的结构,发现它是一个el-input--suffix
的div
包裹着一个input
,如下图所示。
内层input
的宽度是100%,外层div
的宽度是由这个内层input
决定的。也就是说,内层input
的宽度如果动态增加,外层div
的宽度也会随之增加。那么问题来了,如何将内层input
的宽度动态增加呢?
tips:
如果你对width的100%和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