一、问题
提示:el-select的filterable单独过滤筛选使用正常;全选按钮单独使用也正常;但是两者结合使用的时候先过滤再全选会导致数据不正常
;
目标:过滤后的全选希望值增加所过滤的所有相,但是实际会将整体下拉项都选中
二、解决方案
自定义filter-method过滤事件与状态判断修改
封装组件MySelectAll.vue
<template>
<div>
<!-- <div>{{ checkAll }}-{{ indeterminate }}-{{ flterMsg }}-{{ values }}</div> -->
<el-select @blur="blurFun" v-model="values" :filter-method="handleFilter" multiple collapse-tags clearable filterable style="width: 100%" @change="handleCheck">
<template #header>
<el-checkbox v-model="checkAll" :indeterminate="indeterminate" @change="handleCheckAll">全部</el-checkbox>
</template>
<el-option v-for="item in filteredOptions" :key="item" :label="item.name" :value="item.value" />
</el-select>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from "vue"
const emit = defineEmits(["update:modelValue"])
const props = defineProps({
// 传入查询关键字
options: {
type: Array,
default: () => []
},
modelValue: {
// 父组件 v-model 时数据没有指定参数名,所以此时属性modelValue会接收到v-model变量 即 flag1
type: Array,
default: () => []
}
})
let list = ref(props.options || [])
let filteredOptions = ref(props.options || [])
let values = ref(props.modelValue || [])
const checkAll = ref(false)
const indeterminate = ref(false)
let flterMsg = ref(undefined)
watch(
[() => values.value, () => flterMsg.value],
([val, msg]) => {
// 需要监听过滤字段 也触发对用状态判断效果
let a = 1
if (a === 2) {
console.log(msg)
}
if (val == null || val == undefined) {
checkAll.value = false
indeterminate.value = false
} else {
if (val.length === 0) {
checkAll.value = false
indeterminate.value = false
} else {
let hasAllSon = filteredOptions.value.every(ele => val.includes(ele.value))
let hasNoAllSon = filteredOptions.value.every(ele => !val.includes(ele.value))
if (hasNoAllSon) {
checkAll.value = false
indeterminate.value = false
} else if (hasAllSon) {
checkAll.value = true
indeterminate.value = false
} else {
checkAll.value = true
indeterminate.value = true
}
}
}
},
{ deep: true, immediate: true }
)
watch(
() => props.options,
val => {
list.value = val
filteredOptions.value = val
},
{ deep: true, immediate: true }
)
const handleFilter = msg => {
flterMsg.value = msg
filteredOptions.value = list.value.filter(item => item.name.includes(msg))
}
const blurFun = () => {
console.log(1)
flterMsg.value = undefined
}
const handleCheckAll = val => {
console.log(val)
indeterminate.value = false
if (val) {
let arr = JSON.parse(JSON.stringify(values.value))
let arr2 = filteredOptions.value.map(_ => _.value)
values.value = [...new Set([...arr, ...arr2])]
} else {
let arr = JSON.parse(JSON.stringify(values.value))
let arr2 = filteredOptions.value.map(_ => _.value)
values.value = arr.filter(_ => !arr2.includes(_))
}
emit("update:modelValue", values.value)
}
const handleCheck = () => {
emit("update:modelValue", values.value)
}
// 生命周期
onMounted(() => {})
</script>
<style lang="scss" scoped></style>
使用组件
<MySelectAll v-model="networkNameList" :options="networkNameArr" placeholder="请选择网络名称"></MySelectAll>
// networkNameList为双下个绑定选择值
// options为下拉数据