diff --git a/packages/components/form/Form.tsx b/packages/components/form/Form.tsx index cab405e661..a8c8bbf477 100644 --- a/packages/components/form/Form.tsx +++ b/packages/components/form/Form.tsx @@ -54,7 +54,7 @@ const Form = forwardRefWithStatics( const formRef = useRef(null); const formMapRef = useRef(new Map()); // 收集所有包含 name 属性 formItem 实例 const floatingFormDataRef = useRef({}); // 储存游离值的 formData - const formInstance = useInstance(props, formRef, formMapRef, floatingFormDataRef); + const formInstance = useInstance(props, formRef, formMapRef, floatingFormDataRef, form); useImperativeHandle(ref, () => formInstance); Object.assign(form, { ...formInstance }); @@ -71,6 +71,7 @@ const Form = forwardRefWithStatics( }); form?.getInternalHooks?.(HOOK_MARK)?.notifyWatch?.([]); form.store = {}; + floatingFormDataRef.current = {}; onReset?.({ e }); } diff --git a/packages/components/form/hooks/interface.ts b/packages/components/form/hooks/interface.ts index a14ce12407..14a98e8708 100644 --- a/packages/components/form/hooks/interface.ts +++ b/packages/components/form/hooks/interface.ts @@ -1,4 +1,4 @@ -import type { NamePath, FormInstanceFunctions } from '../type'; +import type { FormInstanceFunctions, NamePath } from '../type'; export type Store = Record; @@ -13,6 +13,9 @@ export interface InternalHooks { setForm: (form) => void; } +/** + * @internal + */ export interface InternalFormInstance extends FormInstanceFunctions { _init?: boolean; store?: Store; diff --git a/packages/components/form/hooks/useForm.ts b/packages/components/form/hooks/useForm.ts index e532691526..e12a7a7838 100644 --- a/packages/components/form/hooks/useForm.ts +++ b/packages/components/form/hooks/useForm.ts @@ -1,6 +1,6 @@ import { useState, useRef } from 'react'; import log from '@tdesign/common-js/log/index'; -import type { NamePath } from '../type'; +import type { FormInstanceFunctions, NamePath } from '../type'; import type { WatchCallBack, InternalHooks, InternalFormInstance, Store } from './interface'; export const HOOK_MARK = 'TD_FORM_INTERNAL_HOOKS'; @@ -102,7 +102,7 @@ class FormStore { }; } -export default function useForm(form?: InternalFormInstance) { +export default function useForm(form?: FormInstanceFunctions) { const formRef = useRef(Object.create({})); const [, forceUpdate] = useState({}); diff --git a/packages/components/form/hooks/useInstance.tsx b/packages/components/form/hooks/useInstance.tsx index 335c13c707..5c44d19e43 100644 --- a/packages/components/form/hooks/useInstance.tsx +++ b/packages/components/form/hooks/useInstance.tsx @@ -12,6 +12,7 @@ import type { NamePath, TdFormProps, } from '../type'; +import type { InternalFormInstance } from './interface'; // 检测是否需要校验 默认全量校验 function needValidate(name: NamePath, fields: string[]) { @@ -44,7 +45,8 @@ export default function useInstance( props: TdFormProps, formRef: React.RefObject, formMapRef: React.MutableRefObject>, - floatingFormDataRef: React.RefObject>, + floatingFormDataRef: React.MutableRefObject>, + form: InternalFormInstance, ) { const { classPrefix } = useConfig(); @@ -111,7 +113,10 @@ export default function useInstance( function getFieldValue(name: NamePath) { if (!name) return null; const formItemRef = findFormItem(name, formMapRef); - return formItemRef?.current?.getValue?.(); + if (formItemRef?.current) { + return formItemRef.current.getValue?.(); + } + return get(floatingFormDataRef.current, name); } // 对外方法,获取一组字段名对应的值,当调用 getFieldsValue(true) 时返回所有值 @@ -133,6 +138,8 @@ export default function useInstance( const [name, formItemRef] = entries[i]; processField(name, formItemRef); } + // 即使没有对应的 FormItem 渲染,也返回数据,用于支持动态 set 的场景 + merge(fieldsValue, cloneDeep(floatingFormDataRef.current)); } else { if (!Array.isArray(nameList)) { log.error('Form', 'The parameter of "getFieldsValue" must be an array'); @@ -141,13 +148,21 @@ export default function useInstance( for (let i = 0; i < nameList.length; i++) { const name = nameList[i]; const formItemRef = findFormItem(name, formMapRef); - processField(name, formItemRef); + if (formItemRef?.current) { + processField(name, formItemRef); + } else { + const floatingValue = get(floatingFormDataRef.current, name); + const fieldValue = calcFieldValue(name, floatingValue, !props.supportNumberKey); + merge(fieldsValue, fieldValue); + } } } return cloneDeep(fieldsValue); } - // 对外方法,设置对应 formItem 的值 + /** + * 对外方法,设置对应 FormItem 的值 + */ function setFieldsValue(fields = {}) { const nameLists = objectToArray(fields); nameLists.forEach((nameList) => { @@ -157,11 +172,15 @@ export default function useInstance( formItemRef.current.setValue?.(fieldValue); } else { set(floatingFormDataRef.current, nameList, fieldValue); + // 确保 store 始终包含所有被 set 的字段 + set(form?.store, nameList, fieldValue); } }); } - // 对外方法,设置对应 formItem 的数据 + /** + * 对外方法,设置对应 FormItem 的状态 + */ function setFields(fields = []) { if (!Array.isArray(fields)) throw new TypeError('The parameter of "setFields" must be an array');