el-select如何获取到filterable过滤后的数据;el-select全选与filterable过滤组合使用;

发布于:2025-08-14 ⋅ 阅读:(15) ⋅ 点赞:(0)


一、问题

提示: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为下拉数据


网站公告

今日签到

点亮在社区的每一天
去签到