vue3 + vant4 checkbox多选弹框
实现效果
代码如下
多选组件
DictSelect.vue
<template>
<van-popup :show="showPicker" position="bottom" :style="{ height: '34vh' }">
<div class="con">
<div class="confirmBtns">
<van-button class="qxBtn" @click="handleClose" size="normal"
>取消</van-button
>
<div class="title" size="normal">{{ title }}</div>
<van-button class="qrBtn" @click="onSubmit" size="normal"
>确认</van-button
>
</div>
<div class="checkboxCon">
<van-cell v-if="showTotalBtn" title="全选">
<template #right-icon>
<van-checkbox
v-model="isCheckAll"
:indeterminate="isIndeterminate"
/>
</template>
</van-cell>
<van-checkbox-group
v-model="selectList"
ref="checkboxGroup"
@change="checkedResultChange"
>
<van-cell
v-for="(item, index) in dataList"
:key="index"
:title="`${item.text}`"
>
<template #right-icon>
<van-checkbox :name="item.value" />
</template>
</van-cell>
</van-checkbox-group>
</div>
</div>
</van-popup>
</template>
<script setup>
import { reactive, ref, watch, computed, onMounted } from "vue";
const props = defineProps({
title: {
type: String,
default: ""
},
dataList: {
type: Array,
default: () => []
},
initSelectList: {
type: Array,
default: () => []
},
showTotalBtn: {
type: Boolean,
default: false
}
});
const showPicker = ref(false);
const checkboxGroup = ref();
const isCheckAll = ref(false);
const isIndeterminate = ref(false); // 是否为不确定状态
const selectList = ref([...props.initSelectList]);
const emits = defineEmits(["handleSelect"]);
const handleOpen = () => {
showPicker.value = true;
};
const handleClose = () => {
showPicker.value = false;
// onReset();
};
const onSubmit = () => {
const selectListText = (selectList.value || []).map(s => {
const current = props.dataList.find(d => d.value === s);
return current?.text;
});
emits("handleSelect", { values: selectList.value, texts: selectListText });
handleClose();
};
const checkedResultChange = value => {
const checkedCount = value.length;
isCheckAll.value = checkedCount === props.dataList.length;
isIndeterminate.value =
checkedCount > 0 && checkedCount < props.dataList.length;
};
watch(isCheckAll, (newValue, oldValue) => {
if (newValue) {
checkboxGroup.value.toggleAll(true);
isIndeterminate.value = false;
} else {
checkboxGroup.value.toggleAll();
isIndeterminate.value = false;
}
});
defineExpose({
handleOpen,
handleClose
});
</script>
<style lang="less" scoped>
.con {
.confirmBtns {
display: flex;
justify-content: space-between;
height: 44px;
line-height: 44px;
.title {
border: none;
color: #000;
}
.qxBtn {
border: none;
color: #969799;
}
.qrBtn {
border: none;
color: #1989fa;
}
}
.checkboxCon {
width: 100%;
height: calc(34vh - 44px);
overflow-y: auto;
padding: 10px 0;
}
}
</style>
父组件使用:
<template>
<van-field
v-model="formObj.rangeText"
name="rangeText"
label="多选"
label-align="top"
placeholder="请输入"
type="text"
is-link
readonly
:rules="[{ required: true, message: '请选择' }]"
@click="handlePicker"
/>
<dict-select
ref="pickerRef"
title="请选择"
showTotalBtn
:dataList="dataList"
:initSelectList="formObj.range"
@handleSelect="onConfirm"
/>
</template>
<script setup>
import { ref } from "vue";
const pickerRef = ref();
const formObj = ref({
range: ['1'],
rangeText: ['选项一']
});
const dataList = ref([
{ value: "1", text: "选项一" },
{ value: "2", text: "选项二" },
{ value: "3", text: "选项三" },
{ value: "4", text: "选项四" }
]);
const onConfirm = ({ values, texts }) => {
console.log("value", values, texts);
formObj.value.range = values;
formObj.value.rangeText = (texts || []).join(",");
};
const handlePicker = () => {
pickerRef?.value?.handleOpen && pickerRef?.value?.handleOpen();
};
</script>