因为业务需要用到element多选select组件,但是多选的el组件,只有下面这两种:
但是产品希望的尽可能单行显示,行内尽可能显示多项,超出才用数字显示,具体效果如下:
好了,废话不多说,直接贴组件代码:
/**
* 二次封装的select组件,这里命名为vMutipleSelect
*/
<template>
<div class="v-multiple-select">
<el-select v-model="value" multiple placeholder="请选择" :size="size" @change="handleChange" :style="'width:' + width">
<el-option label="全选" value="all" @click.native="selectAll" v-if="isShowSelectAll"></el-option>
<el-option
v-for="item in list"
:key="item[listValue]"
:label="item[listLabel]"
:value="item[listValue]">
</el-option>
<template slot = "prefix">
<div class="max-tag">
<el-tag v-for="tag in tags" :key="tag[listValue]" closable type="info" @close="removeTag(tag[listValue])" size="small">{{tag[listLabel]}}</el-tag>
<span class="tag-length">{{tagsLength ? '+' + tagsLength : ''}}</span>
</div>
</template>
</el-select>
</div>
</template>
<script>
export default {
name: 'vMultipleSelect',
data () {
return {
value: '',
tags: [],
tagsLength: ''
};
},
props: {
list: { // select的下拉数据
type: Array,
default: () => []
},
listValue: { // 数据值的key字段,默认value
type: String,
default: 'value'
},
listLabel: { // 数据显示文本的key字段,默认label
type: String,
default: 'label'
},
maxTag: { // 文本框显示最大tag数
type: String,
default: '2'
},
size: { // select的size
type: String,
default: 'small'
},
isShowSelectAll: { // 是否有全选选项
type: Boolean,
default: true
},
width: { // select的宽度
type: String,
default: '180px'
}
},
mounted () {
},
methods: {
removeTag (v) {
this.value.splice(this.value.indexOf(v), 1);
this.handleChange(this.value);
},
handleChange (arr) {
this.tags = [];
for (let i = 0; i < this.list.length; i++) {
if (this.tags.length === parseInt(this.maxTag)) break;
if (arr.indexOf(this.list[i][this.listValue]) > -1) {
this.tags.push(this.list[i]);
}
}
this.tagsLength = this.value.length > this.tags.length ? this.value.length - this.tags.length : '';
this.$emit('getSelectValue', this.value);
},
selectAll () {
let valueLen = this.value.length;
this.tags = [];
this.value = [];
if (valueLen === this.list.length + 1) {
this.$emit('getSelectValue', this.value);
this.tagsLength = '';
return;
}
for (let i = 0; i < this.list.length; i++) {
if (i < parseInt(this.maxTag)) {
this.tags.push(this.list[i]);
}
this.value.push(this.list[i][this.listValue]);
}
this.tagsLength = this.value.length > this.tags.length ? this.value.length - this.tags.length : '';
this.$emit('getSelectValue', this.value);
}
}
};
</script>
<style >
.v-multiple-select {
position: relative;
display: flex;
}
.v-multiple-select .el-select {
overflow: hidden;
}
.v-multiple-select .el-select__tags {
display: none;
}
.v-multiple-select .max-tag {
overflow: hidden;
}
.v-multiple-select .max-tag .el-tag.el-tag--info .el-tag__close {
background-color: #C0C4CC;
}
.v-multiple-select .el-input--prefix .el-input__inner {
padding-left: 15px;
}
.v-multiple-select .max-tag .tag-length {
color: #ec7259;
margin-left: 2px;
}
</style>
使用组件:
/**
* 使用组件
*/
<template>
<div class="hello">
<v-multiple-select :list=options listValue='value' listLabel='label' maxTag='3' @getSelectValue="getSelectValue" width="200px" />
</div>
</template>
<script>
import vMultipleSelect from './multipleSelect';
export default {
name: 'HelloWorld',
components: {
vMultipleSelect
},
data () {
return {
options: [{
value: '1',
label: '1'
}, {
value: '2',
label: '2'
}, {
value: '3',
label: '3'
}, {
value: '4',
label: '4'
}, {
value: '5',
label: '5'
}]
}
},
methods: {
getSelectValue(v) {
console.log(v);
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
这个组件,其实还可以根据实际项目中select宽度,自动默认tag显示数量。获取已选中tag宽度和select作对比,这个后续可以自己做扩展。