<!-- 下拉多选 -->
<template>
<div class="select-checked">
<el-select v-model="selected" :class="{ all: optionsAll, hidden: selectedOptions.data.length < 2 }" multiple
placeholder="请选择" :popper-append-to-body="false" collapse-tags popper-class="select-popper">
<template v-if="selectedOptions.data.length > 1" #prefix>
<div class="multi">(多选) x {{ selectedOptions.data.length }}</div>
</template>
<el-option class="multiple" :value="item.value" :label="item.label" v-for="(item, key) in optionsData.data"
:key="key">
<el-checkbox v-model="item.check" @change="handleTaskItemChange(item)" style="width: 100%;">
{{ item.label }}
</el-checkbox>
</el-option>
<div class="is-all">
<div @click="handleOptionsAllChange(true)">全选</div>
<div @click="handleOptionsAllChange(false)">反选</div>
</div>
</el-select>
</div>
</template>
<script setup>
import { ref, reactive, computed, watch, defineProps, onMounted } from 'vue'
let props = defineProps({
options: {
type: Array,
required: true
}
})
let optionsData = reactive({ data: [] })
let selectedOptions = reactive({ data: [] })
let optionsAll = ref(false)
const emit = defineEmits(['selected']);
watch(() => props.options, (newVal) => {
optionsData.data = newVal;
let checkedData = newVal.filter((item) => item.check);
selectedOptions.data = checkedData.map((item) => item.value);
optionsAll.value = checkedData.length === newVal.length;
}, { immediate: true })
onMounted(() => {
// 在控件载入时触发父级的selected方法
emit('selected', selectedOptions.data);
})
const selected = computed({
get() {
return selectedOptions.data.length > props.options.length ? [''] : selectedOptions.data;
},
set(value) {
selectedOptions.data = value;
}
})
const handleOptionsAllChange = (isAll) => {
optionsData.data.forEach((elm) => {
elm.check = isAll;
});
selectedOptions.data = isAll ? optionsData.data.map((item) => item.value) : [];
emit('selected', selectedOptions.data);
}
const handleTaskItemChange = (item) => {
if (!item.check) {
selectedOptions.data = selectedOptions.data.filter((value) => value !== item.value);
} else {
selectedOptions.data.push(item.value);
}
optionsAll = selectedOptions.data.length === optionsData.data.length;
emit('selected', selectedOptions.data);
}
</script>
<style lang="scss">
.select-checked {
width: 420px;
height: 30px;
.el-input {
width: 420px;
height: 30px;
}
// tag删除图标
.el-tag__close,
.el-icon-close {
display: none;
}
// 标签tag背景
.el-tag.el-tag--info {
background: transparent;
border: 0;
display: none;
}
// 第一个显示名称
.hidden {
.el-tag.is-closable.el-tag--default {
display: block;
line-height: 30px;
padding-left: 15px;
font-weight: 400;
color: #333333;
}
}
}
.is-all {
display: flex;
div {
cursor: pointer;
margin: 6px 10px;
transition: 0.2s;
&:hover {
opacity: .7;
}
}
}
.multi {
font-size: 12px;
font-weight: 400;
color: #333333;
}
</style>
<style>
.el-select-dropdown.is-multiple.el-select-dropdown__item.selected::after {
content: none;
}
</style>
使用:
<selectMulti :options="options" @selected="selected"></selectMulti>
let options = [
{
value: '001',
label: '黄金糕',
check: false
},
{
value: '002',
label: '双皮奶',
check: false
},
{
value: '003',
label: '蚵仔煎',
check: false
},
{
value: '004',
label: '龙须面',
check: false
},
{
value: '005',
label: '北京烤鸭',
check: false
}
]
const selected = (value) => {
console.log(value);
}