arco-disign vue + vue3 封装一个“下拉单选组功能”
手搓一个下拉框多组单选组件,实现采用框架 arco-disign vue + vue3组件采用:a-popover、a-input-tag、a-radio-group、a-radio实现效果:调用组件
·
手搓一个下拉框多组单选组件,
实现采用框架 arco-disign vue + vue3
组件采用:a-popover、a-input-tag、a-radio-group、a-radio
实现效果:
调用组件
<SelectGroupRadio
v-model="searchModel.indicatorScreening"
:options="dict.indicatorScreening"
></SelectGroupRadio>
const searchModel = ref({
indicatorScreening: ['01', '04', '05'],
});
const dict = reactive({
indicatorScreening: [
// 动态sql 拼接
[
{ value: '01', label: '超标' },
{ value: '02', label: '非超标' },
],
[
{
value: '03',
label: '已维护',
},
{
value: '04',
label: '未维护',
},
],
[
{
value: '05',
label: '持续',
},
{
value: '06',
label: '非持续',
},
],
],
<!--
实现下拉列表:
多组单选
modelValue:可由此设置默认值,以及获取所选值
options:下拉显示的内容,需要一个二维数组:
例如: [
[
{ value: '01', label: '超标' },
{ value: '02', label: '非超标' },
],
[
{
value: '03',
label: '已豁免',
},
{
value: '04',
label: '未豁免',
},
],
]
-->
<template>
<a-popover position="bl" trigger="click" :arrow-style="{ display: 'none' }">
<a-input-tag
v-model="inputTag"
allow-clear
:max-tag-count="2"
@remove="remove"
@clear="clear"
@input-value-change="null"
@press-enter="null"
/>
<template #content>
<div v-for="(group, index) in props.options" :key="index">
<a-radio-group
:key="index"
v-model="redioModel['model' + index]"
direction="vertical"
style="width: 290px"
@change="change"
>
<a-radio
v-for="(item, iindex) in group"
:key="item.value + iindex"
:value="item.value"
>{{ item.label }}</a-radio
>
</a-radio-group>
<a-divider v-if="index < options.length - 1" />
</div>
</template>
</a-popover>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, computed, watch } from 'vue';
import XEUtils from 'xe-utils';
const props: any = defineProps({
modelValue: {
type: Array,
required: true,
default: () => {
return [];
},
},
options: {
type: Array,
required: true,
default: () => {
return [];
},
},
});
// 初始化每个组的绑定变量
const redioModel = ref<any>({});
props.options.map((item, index) => {
redioModel.value[`model${index}`] = '';
return item;
});
const inputTag = ref([]);
// 回填值
const emits = defineEmits(['update:modelValue', 'resultValue']);
const resultValue = () => {
emits(
'update:modelValue',
XEUtils.flatten(props.options)
.filter((item) => inputTag.value.indexOf(item.label) !== -1)
.map((item) => item.value)
);
};
const change = (value) => {
// 过滤出二维数组中匹配的一组
const groupItem = props.options.filter((gItem, index) => {
if (
gItem.filter((item) => {
return item.value === value;
}).length > 0
) {
redioModel.value[`model${index}`] = value; // 赋值新绑定的值
return true;
}
return false;
})[0];
if (inputTag.value.length > 0) {
// 从tag 中 移除掉该组中所有的选项
groupItem.map((item: any) => {
const index = inputTag.value.indexOf(item.label);
if (index !== -1) {
inputTag.value.splice(index, 1);
}
return item;
});
}
// 向Tag框中赋值当前选择的项
const yesItem = groupItem.filter((item: any) => item.value === value);
yesItem.map((item: any) => {
inputTag.value.push(item.label);
return item;
});
resultValue();
};
// 默认值回填
watch(
() => props.modelValue,
(newValue, oldValue) => {
if (newValue.length > 0) {
XEUtils.flatten(props.options)
.filter((item) => newValue.indexOf(item.value) !== -1)
.map((item) => change(item.value));
}
},
{ deep: true, immediate: true }
);
const clear = () => {
// 清除下拉选项框中绑定的值
props.options.map((item, index) => {
redioModel.value[`model${index}`] = '';
return item;
});
// 清除父组件v-model 绑定的值
inputTag.value = [];
};
const remove = (label) => {
// 1.过滤出二维数组中匹配的一组下标, 根据下标删除
props.options.filter((gItem, index) => {
if (
gItem.filter((item) => {
return item.label === label;
}).length > 0
) {
redioModel.value[`model${index}`] = ''; // 将绑定的值置空
return true;
}
return false;
});
// 移除tag 输入框中对应的元素
const index = inputTag.value.indexOf(label);
if (index !== -1) {
inputTag.value.splice(index, 1);
}
// 重置父组件绑定的值
resultValue();
};
onMounted(() => {});
defineExpose({});
</script>
<style></style>
更多推荐
所有评论(0)