element使用select组件远程搜索时实现全选功能
1.先说思路,远程搜索的时候是没有全选功能的,一开始在公司纠结了半天,要不要把全选写到第一个options里面呢,后来写了后发现,行不通,因为如果是option的话,点了全选,输入框里的标签也会多一个全选标签,这样是不行的,在网上查了资料,有一个比较好的方案,就是结合select和checkbox与checkbox-group这三个组件来实现这个功能。如果统计到选择的个数已经等于当此请求回来opt
1.先说思路,远程搜索的时候是没有全选功能的,一开始在公司纠结了半天,要不要把全选写到第一个options里面呢,后来写了后发现,行不通,因为如果是option的话,点了全选,输入框里的标签也会多一个全选标签,这样是不行的,在网上查了资料,有一个比较好的方案,就是结合select和checkbox与checkbox-group这三个组件来实现这个功能。
2.话不多说,上代码:
<template>
<div class="flex flex-wrap">
<div class="m-4">
<p>实现</p>
<el-select
v-model="biddingStage"
multiple
filterable
remote
reserve-keyword
placeholder="Please enter a keyword"
:remote-method="remoteMethod"
:loading="loading"
style="width: 240px"
@change="handleSelect"
>
<div style="padding: 0 20px; line-height: 34px">
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">全选</el-checkbox>
</div>
<el-checkbox-group v-model="biddingStage">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
<el-checkbox style="pointer-events: none" :label="item.value">
{{ item.value }}
</el-checkbox>
</el-option>
</el-checkbox-group>
</el-select>
</div>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
interface ListItem {
value: string
label: string
}
const list = ref<ListItem[]>([])
const options = ref<ListItem[]>([])
const loading = ref(false)
const checkAll = ref(false) // 是否全选
const isIndeterminate = ref(false) // 全选复选框标识
const biddingStage = ref<string[]>([])
onMounted(() => {
list.value = states.map((item) => {
return { value: `value:${item}`, label: `label:${item}` }
})
})
const remoteMethod = (query: string) => {
if (query) {
loading.value = true
setTimeout(() => {
loading.value = false
options.value = list.value.filter((item) => {
return item.label.toLowerCase().includes(query.toLowerCase())
})
}, 200)
} else {
options.value = []
}
}
const handleSelect = (value: string[]) => {
console.log(value, 'value')
const checkedCount = value.length
checkAll.value = checkedCount === options.value.length
isIndeterminate.value = checkedCount > 0 && checkedCount < options.value.length
const data = value.map((item) => {
return item
})
biddingStage.value = value.length > 0 ? data : []
console.log(biddingStage.value, 'biddingStage')
}
const handleCheckAllChange = (val: boolean) => {
const data = options.value.map((item) => {
return item.value
})
biddingStage.value = val ? data : []
isIndeterminate.value = false
}
const states = [
'Alabama',
'Alaska',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Connecticut',
'Delaware',
'Florida',
'Georgia',
'Hawaii',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Kansas',
'Kentucky',
'Louisiana',
'Maine',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana',
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota',
'Ohio',
'Oklahoma',
'Oregon',
'Pennsylvania',
'Rhode Island',
'South Carolina',
'South Dakota',
'Tennessee',
'Texas',
'Utah',
'Vermont',
'Virginia',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming',
]
</script>
3.解释
UI部分就不说了,直接说逻辑,以下是elementPLUS的截图
这一部分就是实现全选选中的关键,把他放到select中
<div class="flex flex-wrap">
<div class="m-4">
<p>实现</p>
<el-select
v-model="biddingStage"
multiple
filterable
remote
reserve-keyword
placeholder="Please enter a keyword"
:remote-method="remoteMethod"
:loading="loading"
style="width: 240px"
@change="handleSelect"
>
<div style="padding: 0 20px; line-height: 34px">
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange">全选</el-checkbox>
</div>
<el-checkbox-group v-model="biddingStage">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
<el-checkbox style="pointer-events: none" :label="item.value">
{{ item.value }}
</el-checkbox>
</el-option>
</el-checkbox-group>
</el-select>
</div>
</div>
这样就可以看到如下图所示效果
当用户输入的时候请求后端接口并返回数据,这里要记住,每一次返回的数据不同,所以全选要根据每次返回不同的数据的情况去做判断,每次搜索的时候都会触发change事件
触发后
定义一个checkedCount代表当前选中了几个选项,change事件返回的value就是我们选中的值,返回的数据是一个数组,里面由字符串组成
就像这样,此时我们可以去判断是否全选,怎么判断呢?通过和options(搜索调后端接口请求返回来的数据)的长度去进行比较来看,如果当前选中的个数和返回的个数相同就代表全选,否则的话就没有全选,但是这里有一个情况,每一次搜索出来的数据都不相同,如果在原有已经选择的基础上再次去搜索,此时options的值发生了改变,但是value存储的是之前已经选中的值,此时用长度去比较就不太合适。所以要记住checkedCount要根据每次请求回来的options去进行一个更新,checkedCount要根据options里面选中的checked和未选中的option去判断的,我这里因为懒得写接口了,就直接判断了。这时有小伙伴可能有点蒙,怎么去每次判断请求到的options呢,假如搜索A出现了5个选项,此时选了三个,又搜索b,出现了6个选项,其中还有两个是搜索A中搜索出来并且已经选择的,此时就要去看select中v-model中所绑定的数组去判断了
数组中有才会才搜索框中显示标签,就像这样
记住每次的checkedCount一定是跟当此搜索出来的数据去统计,统计完之后就要去判断是否全选了,
如果统计到选择的个数已经等于当此请求回来option的个数,那就证明已经全选了,如果不等于,那就证明还没有全选。
checkAll是用来控制全选按钮是否选中的,isIndeterminate是用来控制全选按钮的不确定状态的
如果选中的个数大于0并且选中的个数小于请求回来的option的个数,返回true,此时代表是半选状态。
全选的话就看biddingStage.value,这个值如果和请求到的option的值的name一样就全选,否如果为【】那就是全不选。
更多推荐
所有评论(0)