props.title || '标题');
@@ -203,23 +203,13 @@ export default defineComponent({
}
};
- const handleSelect = (e: string | number, level: number) => {
- const value = e;
- const index = items[level].findIndex(
- (item: any) => item[(keys as Ref).value?.value ?? 'value'] === value,
- );
- const item = items[level][index];
+ const chooseSelect = (e: string | number, level: number, index: number, item: any) => {
selectedIndexes[level] = index;
selectedIndexes.length = level + 1;
selectedValue[level] = String(e);
selectedValue.length = level + 1;
steps[level] = item[(keys as Ref).value?.label ?? 'label'] as string;
- if (item.disabled) {
- return;
- }
- props.onPick?.({ level, value: item[(keys as Ref).value?.value ?? 'value'], index });
-
if (item[(keys as Ref).value?.children ?? 'children']?.length) {
items[level + 1] = item[(keys as Ref).value?.children ?? 'children'];
items.length = level + 2;
@@ -238,6 +228,40 @@ export default defineComponent({
}
};
+ const cancelSelect = (e: string | number, level: number, index: number, item: any) => {
+ selectedIndexes[level] = index;
+ selectedIndexes.length = level;
+ selectedValue.length = level;
+ steps[level] = String(placeholder.value);
+ steps[level + 1] = placeholder.value;
+ steps.length = level + 1;
+
+ if (item[(keys as Ref).value?.children ?? 'children']?.length) {
+ items[level + 1] = item[(keys as Ref).value?.children ?? 'children'];
+ } else if (item[(keys as Ref).value?.children ?? 'children']?.length === 0) {
+ childrenInfo.value = e;
+ childrenInfo.level = level;
+ }
+ };
+
+ const handleSelect = (e: string | number, level: number) => {
+ const value = e;
+ const index = items[level].findIndex(
+ (item: any) => item[(keys as Ref).value?.value ?? 'value'] === value,
+ );
+ const item = items[level][index];
+ if (item.disabled) {
+ return;
+ }
+ props.onPick?.({ level, value: item[(keys as Ref).value?.value ?? 'value'], index });
+
+ if (checkStrictly.value && selectedValue.includes(String(value))) {
+ cancelSelect(e, level, index, item);
+ } else {
+ chooseSelect(e, level, index, item);
+ }
+ };
+
watch(open, () => {
context.emit('update:visible', open.value);
});
@@ -262,15 +286,34 @@ export default defineComponent({
props.onClose?.({ trigger });
};
- const onVisibleChange = (visible: boolean) => {
+ const onVisibleChange = (visible: boolean, e: any) => {
+ if (e?.trigger !== 'overlay') return;
close('overlay');
};
+ const updateCascaderValue = () => {
+ setCascaderValue(
+ selectedValue[selectedValue.length - 1],
+ items
+ .filter((item, index) => !!item && selectedIndexes.length > index)
+ .map((item, index) => toRaw(item?.[selectedIndexes[index]])),
+ );
+ };
+
const onClose = () => {
open.value = false;
close('close-btn');
};
+ const onCloseBtn = () => {
+ if (checkStrictly.value) {
+ updateCascaderValue();
+ onClose();
+ } else {
+ onClose();
+ }
+ };
+
const onStepClick = (index: number) => {
stepIndex.value = index;
};
@@ -300,6 +343,7 @@ export default defineComponent({
items,
setCascaderValue,
onClose,
+ onCloseBtn,
};
},
});
diff --git a/src/cascader/demos/check-strictly.vue b/src/cascader/demos/check-strictly.vue
new file mode 100644
index 000000000..3f613cfa2
--- /dev/null
+++ b/src/cascader/demos/check-strictly.vue
@@ -0,0 +1,104 @@
+
+
+
+
+ 确定
+
+
+
+
+
+
+
diff --git a/src/cascader/demos/mobile.vue b/src/cascader/demos/mobile.vue
index 29f2258fd..6c58ff60b 100644
--- a/src/cascader/demos/mobile.vue
+++ b/src/cascader/demos/mobile.vue
@@ -20,6 +20,9 @@
+
+
+
diff --git a/src/cascader/props.ts b/src/cascader/props.ts
index 67c8f6354..dedacc5be 100644
--- a/src/cascader/props.ts
+++ b/src/cascader/props.ts
@@ -59,6 +59,11 @@ export default {
},
/** 是否展示 */
visible: Boolean,
+ /** 父子节点选中状态不再关联,可各自选中或取消 */
+ checkStrictly: {
+ type: Boolean,
+ default: false,
+ },
/** 值发生变更时触发 */
onChange: Function as PropType,
/** 关闭时触发 */