<!-- 下拉多选 -->
<template><div class="select-checked"><el-select v-model="selected" :class="{ all: optionsAll, hidden: selectedOptions.data.length < 2 }" multipleplaceholder="请选择" :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);
}