This commit is contained in:
dap
2025-04-16 21:33:11 +08:00
9 changed files with 60 additions and 17 deletions

View File

@@ -62,7 +62,7 @@ async function handleReset(e: Event) {
e?.stopPropagation();
const props = unref(rootProps);
const values = toRaw(props.formApi?.getValues());
const values = toRaw(await props.formApi?.getValues());
if (isFunction(props.handleReset)) {
await props.handleReset?.(values);

View File

@@ -378,7 +378,10 @@ export interface VbenFormProps<
/**
* 表单值变化回调
*/
handleValuesChange?: (values: Record<string, any>) => void;
handleValuesChange?: (
values: Record<string, any>,
fieldsChanged: string[],
) => void;
/**
* 重置按钮参数
*/

View File

@@ -1,12 +1,13 @@
<script setup lang="ts">
import type { Recordable } from '@vben-core/typings';
import type { ExtendedFormApi, VbenFormProps } from './types';
// import { toRaw, watch } from 'vue';
import { nextTick, onMounted, watch } from 'vue';
// import { isFunction } from '@vben-core/shared/utils';
import { useForwardPriorityValues } from '@vben-core/composables';
import { cloneDeep } from '@vben-core/shared/utils';
import { cloneDeep, get, isEqual, set } from '@vben-core/shared/utils';
import { useDebounceFn } from '@vueuse/core';
@@ -61,16 +62,46 @@ function handleKeyDownEnter(event: KeyboardEvent) {
}
const handleValuesChangeDebounced = useDebounceFn(async () => {
forward.value.handleValuesChange?.(
cloneDeep(await forward.value.formApi.getValues()),
);
state.value.submitOnChange && forward.value.formApi?.validateAndSubmitForm();
}, 300);
const valuesCache: Recordable<any> = {};
onMounted(async () => {
// 只在挂载后开始监听form.values会有一个初始化的过程
await nextTick();
watch(() => form.values, handleValuesChangeDebounced, { deep: true });
watch(
() => form.values,
async (newVal) => {
if (forward.value.handleValuesChange) {
const fields = state.value.schema?.map((item) => {
return item.fieldName;
});
if (fields && fields.length > 0) {
const changedFields: string[] = [];
fields.forEach((field) => {
const newFieldValue = get(newVal, field);
const oldFieldValue = get(valuesCache, field);
if (!isEqual(newFieldValue, oldFieldValue)) {
changedFields.push(field);
set(valuesCache, field, newFieldValue);
}
});
if (changedFields.length > 0) {
// 调用handleValuesChange回调传入所有表单值的深拷贝和变更的字段列表
forward.value.handleValuesChange(
cloneDeep(await forward.value.formApi.getValues()),
changedFields,
);
}
}
}
handleValuesChangeDebounced();
},
{ deep: true },
);
});
</script>

View File

@@ -9,7 +9,11 @@ vi.mock('@vben-core/shared/store', () => {
return {
isFunction: (fn: any) => typeof fn === 'function',
Store: class {
get state() {
return this._state;
}
private _state: DrawerState;
private options: any;
constructor(initialState: DrawerState, options: any) {
@@ -25,10 +29,6 @@ vi.mock('@vben-core/shared/store', () => {
this._state = fn(this._state);
this.options.onUpdate();
}
get state() {
return this._state;
}
},
};
});
@@ -54,7 +54,6 @@ describe('drawerApi', () => {
});
it('should close the drawer if onBeforeClose allows it', () => {
drawerApi.open();
drawerApi.close();
expect(drawerApi.store.state.isOpen).toBe(false);
});

View File

@@ -86,7 +86,8 @@ export class DrawerApi {
}
/**
* 关闭弹窗
* 关闭抽屉
* @description 关闭抽屉时会调用 onBeforeClose 钩子函数,如果 onBeforeClose 返回 false则不关闭弹窗
*/
async close() {
// 通过 onBeforeClose 钩子函数来判断是否允许关闭弹窗

View File

@@ -186,7 +186,7 @@ const getAppendTo = computed(() => {
});
const getForceMount = computed(() => {
return !unref(destroyOnClose);
return !unref(destroyOnClose) && unref(firstOpened);
});
function handleClosed() {