这是一个基于Vue 3和Ant Design的下拉选择框组件。以下是组件的代码和样式。
模板部分
<template>
<a-select
ref="selectRef" // 下拉选择框的引用
v-model:value="newValue" // 绑定选择值的双向绑定
:mode="(mode as any)" // 选择模式
max-tag-count="responsive"
:placeholder="placeholder" // 占位符
:allowClear="allowClear" // 是否允许清除
:show-search="showSearch" // 是否显示搜索框
:options="lists" // 下拉选项
:filter-option="filterOption" // 搜索过滤函数
:field-names="{ label: 'value', value: 'id'}" // 下拉选项字段映射
:dropdownMatchSelectWidth="mode != undefined ? dropdownMatchSelectWidth : 0" // 下拉菜单宽度
:showArrow="true"
>
<template v-if="mode != undefined" #dropdownRender @mousedown.prevent>
<div @mousedown.prevent class="check-content">
<div class="check-item">
<a-checkbox v-model:checked="allchecked" @change="onCheckAllChange(allchecked)"></a-checkbox>
<span @click="onCheckAllChange(!allchecked)">全部</span>
</div>
<div v-for="(item,index) in lists" :key="index" class="check-item">
<a-checkbox v-model:checked="item.checked" @change="handleCheck(item,item.checked)"></a-checkbox>
<span @click="handleCheck(item,!item.checked)">{{ item.value }}</span>
</div>
</div>
</template>
</a-select>
</template>
js部分
<script lang="ts" setup>
import { ref, computed, watch, defineExpose } from 'vue';
import { getGoodsName, getDeliveryPlanGoodsName, getDeliveryPlanEditGoodsName } from '@/api/base'
import { useStore } from 'vuex';
const store = useStore();
const level = computed<number>(() => store.getters.level || 1);
const selectRef = ref<any>(null); // 下拉选择框的引用
const props = defineProps({
value:{type: [String,Number,Array]}, // 选择值
placeholder: {type: String, default: '请选择物料'}, // 占位符
allowClear: {type: Boolean, default: false}, // 是否允许清除
showAll:{type: Boolean, default: true}, // 是否显示全部选项
showSearch: {type: Boolean, default: true}, // 是否显示搜索框
mode: {type:String, default: undefined}, // 选择模式
dropdownMatchSelectWidth: { type: Number, default: 400 }, // 下拉菜单宽度
scId: {default: ''}, // 公司ID
cgId: {default: ''}, // 类别ID
ctId: {default: ''}, // 客户ID
isPlanModule: {type: Boolean, default: false}, // 是否是计划模块
isPlanModuleEdit: {type: Boolean, default: false} // 是否是计划模块(编辑状态)
})
const emits = defineEmits(['update:value']) // 更新选择值的事件
const newValue = computed<any>({
get() {
return props.value
},
set(value) {
return emits('update:value', value)
}
})
watch(() => newValue.value,() => {
if(props.mode){
if(lists.value.length > 0){
allchecked.value = newValue.value.length == lists.value.length ? true : false;
}else{
allchecked.value = false;
}
if(newValue.value.length == 0){
lists.value.forEach((ele:any) => {
ele.checked = false
})
}
}
})
const allchecked = ref<boolean>(false); // 全选状态
function onCheckAllChange(e:boolean){
allchecked.value = e; // 更新全选状态
lists.value.forEach((ele:any) => {
ele.checked = allchecked.value // 更新每个选项的选中状态
})
newValue.value = lists.value.filter((ele:any) => {
return ele.checked
}).map((ele:any) => {
return ele.id // 更新选择值
})
}
function handleCheck(item:any,flag:boolean){
item.checked = flag; // 更新选项的选中状态
newValue.value = lists.value.filter((ele:any) => {
return ele.checked
}).map((ele:any) => {
return ele.id // 更新选择值
})
}
const lists = ref<any[]>([]) // 下拉选项列表
const getList = () => {
if(props.isPlanModule){
getDeliveryPlanGoodsName({
customerId: props.ctId
}).then((res:any) => {
lists.value = [...res.data]; // 获取计划模块的物料列表
if(props.showAll && props.mode == undefined) lists.value.unshift({id: '', value: '全部'}) // 添加全部选项
})
}else if(props.isPlanModuleEdit){
getDeliveryPlanEditGoodsName({
customerId: props.ctId
}).then((res:any) => {
lists.value = [...res.data]; // 获取计划模块编辑状态的物料列表
if(props.showAll && props.mode == undefined) lists.value.unshift({id: '', value: '全部'}) // 添加全部选项
})
}else{
getGoodsName({
secondCompanyId: level.value == 1 ? props.scId : store.getters.info.deptId.toString(),
categoryId: props.cgId
}).then((res:any) => {
lists.value = [...res.data]; // 获取物料列表
if(props.showAll && props.mode == undefined) lists.value.unshift({id: '', value: '全部'}) // 添加全部选项
})
}
}
getList(); // 初始化获取列表
watch(() => [props.scId, props.cgId, props.ctId], () => {
newValue.value = props.showAll ? (props.mode ? [] : '') : (props.mode ? [] : undefined); // 根据显示全部选项和选择模式重置选择值
getList(); // 重新获取列表
})
const filterOption = (input: string, option: any) => {
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0; // 根据输入筛选选项
};
defineExpose({ getList }) // 暴露获取列表方法
</script>
css样式部分
<style lang="less" scoped>
.check-content{
width: 100%;
padding: 0 12px;
display: flex;
flex-wrap: wrap;
.check-item{
width: 33%;
padding: 8px;
span{
padding: 0 8px;
cursor: pointer;
}
}
}
</style>
以上就是完整的组件代码。在模板部分,我们使用了Ant Design的a-select组件来实现下拉选择框功能,根据需要添加了一些相关属性和事件处理函数。脚本部分包含了一些用于处理选择值、获取选项列表和更新选择状态的逻辑。样式部分定义了一些简单的样式规则。
子组件使用
# 使用子组件
要在父组件中使用子组件,需要引入它并在父组件的模板中进行使用。
```vue
<template>
<div>
<MySelect
v-model="selectedValue"
:showAll="true"
placeholder="请选择物料"
:scId="companyId"
:cgId="categoryId"
:ctId="customerId"
/>
</div>
</template>
<script lang="ts">
import MySelect from '@/components/MySelect.vue';
export default {
components: {
MySelect
},
data() {
return {
selectedValue: '',
companyId: '123', // 公司ID
categoryId: '456', // 类别ID
customerId: '789' // 客户ID
};
}
};
</script>
效果