需求
实现一个带输入框,可手动输入的多选选择器。
需求
- 下拉时出现输入框可以自定义修改选择项
- 可以删除任意一个选择项
- 选择器里只显示固定的选择,在右边显示总共的选择数量
输入时
点击空白处收起
组件代码
<template>
<div>
<a-select
v-model="ipList"
mode="multiple"
:open="open"
:showArrow="true"
:placeholder="placeholder"
:maxTagCount="2"
:get-popup-container="getPopupContainer"
@deselect="deselect"
@focus="selectFocus"
>
<span slot="suffixIcon" class="suffixIcon">
<span>共{{ ipList.length }}项</span>
<a-icon type="down" :class="open ? 'suffixIconStart1' : 'suffixIconEnd1'" />
</span>
<div
slot="dropdownRender"
class="dropdownRender"
@click="
e => {
e.stopPropagation();
}
"
>
<a-input
class="child-input"
v-for="(item, index) in ipArr"
:key="index"
:ref="'ipArr' + index"
v-model="ipArr[index]"
size="large"
:allowClear="false"
:placeholder="placeholder"
@change="add()"
>
<a-icon slot="suffix" type="close" @click="close(item)" />
</a-input>
</div>
</a-select>
</div>
</template>
<script>
import { cloneDeep } from 'lodash';
export default {
name: '',
components: {},
props: {
data: {
type: Array,
default: () => [],
},
placeholder: {
type: String,
default: '',
},
},
data() {
return {
open: false,
ipArr: [''],
ipList: this.data,
};
},
watch: {
data: {
immediate: true,
deep: true,
handler(val) {
this.ipList = val;
if (this.ipList.length == 0) {
this.ipArr = [''];
} else {
this.ipArr = [...val, ''];
}
},
},
ipList: {
deep: true,
handler(val) {
this.$emit('update:data', val);
this.onChange();
},
},
},
mounted() {
// 点击空白处关闭下拉框
this.clickHandle = e => {
if (e.target && 'className' in e.target && this.open) {
const className = e.target.className;
if (className.indexOf('child-input') === -1) {
this.open = false;
if (this.open == false) {
this.ipList = cloneDeep(this.ipArr).slice(0, this.ipArr.length - 1);
}
this.$emit('update:data', this.ipList);
this.onChange();
}
}
};
document.body.addEventListener('click', this.clickHandle);
},
beforeDestroy() {
document.body.removeEventListener('click', this.clickHandle);
this.clickHandle = null;
},
methods: {
// 传给父组件进行规则校验
onChange() {
this.$emit('change');
},
getPopupContainer() {
return document.getElementsByClassName('childForm')[0];
},
selectFocus() {
this.open = true;
},
clickSuffixIcon() {
this.open = !this.open;
if (this.open == false) {
this.ipList = cloneDeep(this.ipArr).slice(0, this.ipArr.length - 1);
}
this.$emit('update:data', this.ipList);
this.onChange();
},
// 前面都填完才增加一个input
add() {
const noEmpty = this.ipArr.slice(0, this.ipArr.length).every(item => item !== '');
if (noEmpty) {
this.ipArr.push('');
}
},
// 删除时更新下拉框内容的input数量和数据
deselect(value, option) {
this.ipArr = this.ipArr.filter(item => item !== value);
},
// 删除下拉框某条数据时更新下拉框内容的input数量和数据
close(value) {
this.ipArr = this.ipArr.filter(item => item !== value);
},
},
};
</script>
<style lang="less" scoped>
.dropdownRender {
max-height: 260px;
overflow: auto;
padding: 10px;
.a-input-affix-wrapper {
margin-bottom: 5px;
}
}
/deep/ .a-select-selection__choice__disabled {
display: none;
}
/deep/ .a-select-selection--multiple {
max-height: 32px;
}
.suffixIcon {
display: flex;
align-items: center;
span {
margin-right: 10px;
}
}
.suffixIconStart1 svg {
transform: rotate(180deg);
transition: all 0.3s ease-in-out;
}
.suffixIconEnd1 svg {
transform: rotate(0deg);
transition: all 0.3s ease-in-out;
}
// 滚动条样式
.webkitScrollbar();
</style>