From edb4c4607eeb189aec351e05bceda3a2ff9e1845 Mon Sep 17 00:00:00 2001 From: xiaoyu2er Date: Fri, 25 Apr 2025 20:56:31 +0000 Subject: [PATCH 1/2] docs: update documentation translations --- docs/zh-hant/comparison.md | 59 ++ docs/zh-hant/config.json | 612 +++++++++++++++++ .../framework/angular/guides/validation.md | 542 ++++++++++++++++ docs/zh-hant/framework/angular/quick-start.md | 62 ++ .../reference/classes/tanstackfield.md | 312 +++++++++ .../angular/reference/functions/injectform.md | 47 ++ .../reference/functions/injectstore.md | 53 ++ .../framework/angular/reference/index.md | 18 + docs/zh-hant/framework/lit/guides/arrays.md | 175 +++++ .../framework/lit/guides/basic-concepts.md | 103 +++ docs/zh-hant/framework/lit/quick-start.md | 85 +++ docs/zh-hant/framework/lit/reference/index.md | 13 + .../react/community/balastrong-tutorial.md | 37 ++ docs/zh-hant/framework/react/guides/arrays.md | 125 ++++ .../react/guides/async-initial-values.md | 51 ++ .../framework/react/guides/basic-concepts.md | 361 ++++++++++ .../framework/react/guides/custom-errors.md | 280 ++++++++ .../framework/react/guides/debugging.md | 43 ++ .../react/guides/form-composition.md | 407 ++++++++++++ .../framework/react/guides/linked-fields.md | 80 +++ .../framework/react/guides/listeners.md | 127 ++++ .../framework/react/guides/react-native.md | 31 + .../framework/react/guides/reactivity.md | 53 ++ docs/zh-hant/framework/react/guides/ssr.md | 493 ++++++++++++++ .../react/guides/submission-handling.md | 41 ++ .../framework/react/guides/ui-libraries.md | 127 ++++ .../framework/react/guides/validation.md | 554 ++++++++++++++++ docs/zh-hant/framework/react/quick-start.md | 137 ++++ .../react/reference/functions/field.md | 69 ++ .../react/reference/functions/usefield.md | 69 ++ .../react/reference/functions/useform.md | 49 ++ .../react/reference/functions/usetransform.md | 27 + .../framework/react/reference/index.md | 30 + .../reference/type-aliases/fieldcomponent.md | 77 +++ .../react/reference/type-aliases/usefield.md | 69 ++ docs/zh-hant/framework/solid/guides/arrays.md | 125 ++++ .../solid/guides/async-initial-values.md | 49 ++ .../framework/solid/guides/basic-concepts.md | 296 +++++++++ .../framework/solid/guides/linked-fields.md | 78 +++ .../framework/solid/guides/validation.md | 447 +++++++++++++ docs/zh-hant/framework/solid/quick-start.md | 55 ++ .../solid/reference/functions/createfield.md | 67 ++ .../solid/reference/functions/createform.md | 45 ++ .../solid/reference/functions/field.md | 65 ++ .../framework/solid/reference/index.md | 25 + .../reference/type-aliases/createfield.md | 71 ++ .../reference/type-aliases/fieldcomponent.md | 73 +++ .../zh-hant/framework/svelte/guides/arrays.md | 112 ++++ .../svelte/guides/async-initial-values.md | 51 ++ .../framework/svelte/guides/basic-concepts.md | 289 +++++++++ .../framework/svelte/guides/linked-fields.md | 80 +++ .../framework/svelte/guides/validation.md | 407 ++++++++++++ docs/zh-hant/framework/vue/guides/arrays.md | 149 +++++ .../vue/guides/async-initial-values.md | 60 ++ .../framework/vue/guides/basic-concepts.md | 351 ++++++++++ .../framework/vue/guides/linked-fields.md | 85 +++ .../framework/vue/guides/validation.md | 501 ++++++++++++++ docs/zh-hant/framework/vue/quick-start.md | 48 ++ .../vue/reference/functions/usefield.md | 77 +++ .../vue/reference/functions/useform.md | 47 ++ docs/zh-hant/framework/vue/reference/index.md | 31 + .../reference/type-aliases/fieldcomponent.md | 55 ++ .../vue/reference/type-aliases/usefield.md | 77 +++ docs/zh-hant/installation.md | 87 +++ docs/zh-hant/overview.md | 143 ++++ docs/zh-hant/philosophy.md | 77 +++ docs/zh-hant/reference/classes/fieldapi.md | 523 +++++++++++++++ docs/zh-hant/reference/classes/formapi.md | 614 ++++++++++++++++++ .../reference/functions/formoptions.md | 27 + docs/zh-hant/reference/functions/mergeform.md | 33 + docs/zh-hant/reference/index.md | 90 +++ .../reference/interfaces/fieldapioptions.md | 195 ++++++ .../reference/interfaces/fieldoptions.md | 133 ++++ .../reference/interfaces/fieldvalidators.md | 203 ++++++ .../reference/interfaces/formoptions.md | 199 ++++++ .../reference/interfaces/formvalidators.md | 131 ++++ .../reference/type-aliases/baseformstate.md | 129 ++++ .../reference/type-aliases/deepkeys.md | 21 + .../reference/type-aliases/deepvalue.md | 23 + .../type-aliases/derivedformstate.md | 139 ++++ .../reference/type-aliases/fieldmeta.md | 51 ++ .../reference/type-aliases/fieldstate.md | 69 ++ .../zh-hant/reference/type-aliases/updater.md | 21 + .../reference/type-aliases/updaterfn.md | 31 + .../reference/type-aliases/validationerror.md | 15 + .../reference/type-aliases/validationmeta.md | 27 + docs/zh-hant/typescript.md | 15 + 87 files changed, 12230 insertions(+) create mode 100644 docs/zh-hant/comparison.md create mode 100644 docs/zh-hant/config.json create mode 100644 docs/zh-hant/framework/angular/guides/validation.md create mode 100644 docs/zh-hant/framework/angular/quick-start.md create mode 100644 docs/zh-hant/framework/angular/reference/classes/tanstackfield.md create mode 100644 docs/zh-hant/framework/angular/reference/functions/injectform.md create mode 100644 docs/zh-hant/framework/angular/reference/functions/injectstore.md create mode 100644 docs/zh-hant/framework/angular/reference/index.md create mode 100644 docs/zh-hant/framework/lit/guides/arrays.md create mode 100644 docs/zh-hant/framework/lit/guides/basic-concepts.md create mode 100644 docs/zh-hant/framework/lit/quick-start.md create mode 100644 docs/zh-hant/framework/lit/reference/index.md create mode 100644 docs/zh-hant/framework/react/community/balastrong-tutorial.md create mode 100644 docs/zh-hant/framework/react/guides/arrays.md create mode 100644 docs/zh-hant/framework/react/guides/async-initial-values.md create mode 100644 docs/zh-hant/framework/react/guides/basic-concepts.md create mode 100644 docs/zh-hant/framework/react/guides/custom-errors.md create mode 100644 docs/zh-hant/framework/react/guides/debugging.md create mode 100644 docs/zh-hant/framework/react/guides/form-composition.md create mode 100644 docs/zh-hant/framework/react/guides/linked-fields.md create mode 100644 docs/zh-hant/framework/react/guides/listeners.md create mode 100644 docs/zh-hant/framework/react/guides/react-native.md create mode 100644 docs/zh-hant/framework/react/guides/reactivity.md create mode 100644 docs/zh-hant/framework/react/guides/ssr.md create mode 100644 docs/zh-hant/framework/react/guides/submission-handling.md create mode 100644 docs/zh-hant/framework/react/guides/ui-libraries.md create mode 100644 docs/zh-hant/framework/react/guides/validation.md create mode 100644 docs/zh-hant/framework/react/quick-start.md create mode 100644 docs/zh-hant/framework/react/reference/functions/field.md create mode 100644 docs/zh-hant/framework/react/reference/functions/usefield.md create mode 100644 docs/zh-hant/framework/react/reference/functions/useform.md create mode 100644 docs/zh-hant/framework/react/reference/functions/usetransform.md create mode 100644 docs/zh-hant/framework/react/reference/index.md create mode 100644 docs/zh-hant/framework/react/reference/type-aliases/fieldcomponent.md create mode 100644 docs/zh-hant/framework/react/reference/type-aliases/usefield.md create mode 100644 docs/zh-hant/framework/solid/guides/arrays.md create mode 100644 docs/zh-hant/framework/solid/guides/async-initial-values.md create mode 100644 docs/zh-hant/framework/solid/guides/basic-concepts.md create mode 100644 docs/zh-hant/framework/solid/guides/linked-fields.md create mode 100644 docs/zh-hant/framework/solid/guides/validation.md create mode 100644 docs/zh-hant/framework/solid/quick-start.md create mode 100644 docs/zh-hant/framework/solid/reference/functions/createfield.md create mode 100644 docs/zh-hant/framework/solid/reference/functions/createform.md create mode 100644 docs/zh-hant/framework/solid/reference/functions/field.md create mode 100644 docs/zh-hant/framework/solid/reference/index.md create mode 100644 docs/zh-hant/framework/solid/reference/type-aliases/createfield.md create mode 100644 docs/zh-hant/framework/solid/reference/type-aliases/fieldcomponent.md create mode 100644 docs/zh-hant/framework/svelte/guides/arrays.md create mode 100644 docs/zh-hant/framework/svelte/guides/async-initial-values.md create mode 100644 docs/zh-hant/framework/svelte/guides/basic-concepts.md create mode 100644 docs/zh-hant/framework/svelte/guides/linked-fields.md create mode 100644 docs/zh-hant/framework/svelte/guides/validation.md create mode 100644 docs/zh-hant/framework/vue/guides/arrays.md create mode 100644 docs/zh-hant/framework/vue/guides/async-initial-values.md create mode 100644 docs/zh-hant/framework/vue/guides/basic-concepts.md create mode 100644 docs/zh-hant/framework/vue/guides/linked-fields.md create mode 100644 docs/zh-hant/framework/vue/guides/validation.md create mode 100644 docs/zh-hant/framework/vue/quick-start.md create mode 100644 docs/zh-hant/framework/vue/reference/functions/usefield.md create mode 100644 docs/zh-hant/framework/vue/reference/functions/useform.md create mode 100644 docs/zh-hant/framework/vue/reference/index.md create mode 100644 docs/zh-hant/framework/vue/reference/type-aliases/fieldcomponent.md create mode 100644 docs/zh-hant/framework/vue/reference/type-aliases/usefield.md create mode 100644 docs/zh-hant/installation.md create mode 100644 docs/zh-hant/overview.md create mode 100644 docs/zh-hant/philosophy.md create mode 100644 docs/zh-hant/reference/classes/fieldapi.md create mode 100644 docs/zh-hant/reference/classes/formapi.md create mode 100644 docs/zh-hant/reference/functions/formoptions.md create mode 100644 docs/zh-hant/reference/functions/mergeform.md create mode 100644 docs/zh-hant/reference/index.md create mode 100644 docs/zh-hant/reference/interfaces/fieldapioptions.md create mode 100644 docs/zh-hant/reference/interfaces/fieldoptions.md create mode 100644 docs/zh-hant/reference/interfaces/fieldvalidators.md create mode 100644 docs/zh-hant/reference/interfaces/formoptions.md create mode 100644 docs/zh-hant/reference/interfaces/formvalidators.md create mode 100644 docs/zh-hant/reference/type-aliases/baseformstate.md create mode 100644 docs/zh-hant/reference/type-aliases/deepkeys.md create mode 100644 docs/zh-hant/reference/type-aliases/deepvalue.md create mode 100644 docs/zh-hant/reference/type-aliases/derivedformstate.md create mode 100644 docs/zh-hant/reference/type-aliases/fieldmeta.md create mode 100644 docs/zh-hant/reference/type-aliases/fieldstate.md create mode 100644 docs/zh-hant/reference/type-aliases/updater.md create mode 100644 docs/zh-hant/reference/type-aliases/updaterfn.md create mode 100644 docs/zh-hant/reference/type-aliases/validationerror.md create mode 100644 docs/zh-hant/reference/type-aliases/validationmeta.md create mode 100644 docs/zh-hant/typescript.md diff --git a/docs/zh-hant/comparison.md b/docs/zh-hant/comparison.md new file mode 100644 index 000000000..de5b9929b --- /dev/null +++ b/docs/zh-hant/comparison.md @@ -0,0 +1,59 @@ +--- +source-updated-at: '2025-03-05T09:46:22.000Z' +translation-updated-at: '2025-04-25T20:31:55.484Z' +id: comparison +title: 比較 +--- +> ⚠️ 此比較表格正在建構中,內容尚未完全準確。如果您使用過其中任何函式庫並認為資訊可以改進,歡迎透過頁面底部的「Edit this page on Github」連結提出修改建議(需附上說明或佐證資料)。 + +功能/能力對照說明: + +- ✅ 原生支援、內建功能,無需額外設定或程式碼即可使用 +- 🟡 支援,但需透過非官方的第三方或社群函式庫/貢獻 +- 🔶 支援且有文件說明,但需要使用者自行撰寫額外程式碼來實作 +- 🛑 官方不支援或無相關文件 + +| 功能 | TanStack Form | Formik | Redux Form | React Hook Form | Final Form | +| ---------------------------------------------- | -------------------------------------------- | ------------------------------ | -------------------------------------- | ------------------------------------------------ | -------------------------------------- | +| GitHub 儲存庫/星數 | [![][stars-tanstack-form]][gh-tanstack-form] | [![][stars-formik]][gh-formik] | [![][stars-redux-form]][gh-redux-form] | [![][stars-react-hook-form]][gh-react-hook-form] | [![][stars-final-form]][gh-final-form] | +| 支援的框架 | React, Vue, Angular, Solid, Lit | React | React | React | React, Vue, Angular, Solid, Vanilla JS | +| 套件大小 | [![][bp-tanstack-form]][bpl-tanstack-form] | [![][bp-formik]][bpl-formik] | [![][bp-redux-form]][bpl-redux-form] | [![][bp-react-hook-form]][bpl-react-hook-form] | [![][bp-final-form]][bpl-final-form] | +| 完善的 TypeScript 支援 | ✅ | ❓ | ❓ | ✅ | ✅ | +| 完整的 TypeScript 型別推論(包含深層欄位) | ✅ | ❓ | ❓ | ✅ | 🛑 | +| 無頭 UI 元件 (Headless UI) | ✅ | ❓ | ❓ | ✅ | ❓ | +| 框架無關性 | ✅ | ❓ | ❓ | 🛑 | ✅ | +| 細粒度響應式更新 | ✅ | ❓ | ❓ | ❓ | ✅ | +| 支援巢狀物件/陣列欄位 | ✅ | ✅ | ❓ | ✅\*(1) | ✅ | +| 非同步驗證 | ✅ | ✅ | ❓ | ✅ | ✅ | +| 內建非同步驗證防抖動 | ✅ | ❓ | ❓ | ❓ | ❓ | +| 基於結構描述的驗證 (Schema-based Validation) | ✅ | ✅ | ❓ | ✅ | ❓ | +| 官方開發者工具 | 🛑\*(2) | 🛑 | ✅\*(3) | ✅ | ❓ | +| 伺服器渲染整合 (SSR) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 | +| React 編譯器支援 | ✅ | ❓ | ❓ | 🛑 | ❓ | + +\*(1) 對於巢狀陣列,若使用 TypeScript,react-hook-form 要求您[需透過欄位名稱轉換欄位陣列](https://react-hook-form.com/docs/usefieldarray) + +\*(2) 規劃中 + +\*(3) 透過 Redux Devtools 實現 + +[bpl-tanstack-form]: https://bundlephobia.com/result?p=@tanstack/react-form +[bp-tanstack-form]: https://badgen.net/bundlephobia/minzip/@tanstack/react-form?label=💾 +[gh-tanstack-form]: https://github.com/TanStack/form +[stars-tanstack-form]: https://img.shields.io/github/stars/TanStack/form?label=%F0%9F%8C%9F +[bpl-formik]: https://bundlephobia.com/result?p=formik +[bp-formik]: https://badgen.net/bundlephobia/minzip/formik?label=💾 +[gh-formik]: https://github.com/jaredpalmer/formik +[stars-formik]: https://img.shields.io/github/stars/jaredpalmer/formik?label=%F0%9F%8C%9F +[bpl-redux-form]: https://bundlephobia.com/result?p=redux-form +[bp-redux-form]: https://badgen.net/bundlephobia/minzip/redux-form?label=💾 +[gh-redux-form]: https://github.com/redux-form/redux-form +[stars-redux-form]: https://img.shields.io/github/stars/redux-form/redux-form?label=%F0%9F%8C%9F +[bpl-react-hook-form]: https://bundlephobia.com/result?p=react-hook-form +[bp-react-hook-form]: https://badgen.net/bundlephobia/minzip/react-hook-form?label=💾 +[gh-react-hook-form]: https://github.com/react-hook-form/react-hook-form +[stars-react-hook-form]: https://img.shields.io/github/stars/react-hook-form/react-hook-form?label=%F0%9F%8C%9F +[bpl-final-form]: https://bundlephobia.com/result?p=final-form +[bp-final-form]: https://badgen.net/bundlephobia/minzip/final-form?label=💾 +[gh-final-form]: https://github.com/final-form/final-form +[stars-final-form]: https://img.shields.io/github/stars/final-form/final-form?label=%F0%9F%8C%9F diff --git a/docs/zh-hant/config.json b/docs/zh-hant/config.json new file mode 100644 index 000000000..5632a7a2e --- /dev/null +++ b/docs/zh-hant/config.json @@ -0,0 +1,612 @@ +{ + "$schema": "https://raw.githubusercontent.com/TanStack/tanstack.com/main/tanstack-docs-config.schema.json", + "docSearch": { + "appId": "", + "apiKey": "", + "indexName": "tanstack-form" + }, + "sections": [ + { + "label": "入門指南", + "children": [ + { + "label": "概述", + "to": "overview" + }, + { + "label": "安裝", + "to": "installation" + }, + { + "label": "設計理念", + "to": "philosophy" + }, + { + "label": "比較", + "to": "comparison" + }, + { + "label": "TypeScript", + "to": "typescript" + } + ], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "快速開始", + "to": "framework/react/quick-start" + } + ] + }, + { + "label": "vue", + "children": [ + { + "label": "快速開始", + "to": "framework/vue/quick-start" + } + ] + }, + { + "label": "angular", + "children": [ + { + "label": "快速開始", + "to": "framework/angular/quick-start" + } + ] + }, + { + "label": "solid", + "children": [ + { + "label": "快速開始", + "to": "framework/solid/quick-start" + } + ] + }, + { + "label": "lit", + "children": [ + { + "label": "快速開始", + "to": "framework/lit/quick-start" + } + ] + }, + { + "label": "svelte", + "children": [ + { + "label": "快速開始", + "to": "framework/svelte/quick-start" + } + ] + } + ] + }, + { + "label": "指南", + "children": [], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "基本概念", + "to": "framework/react/guides/basic-concepts" + }, + { + "label": "表單驗證", + "to": "framework/react/guides/validation" + }, + { + "label": "非同步初始值", + "to": "framework/react/guides/async-initial-values" + }, + { + "label": "陣列", + "to": "framework/react/guides/arrays" + }, + { + "label": "關聯欄位", + "to": "framework/react/guides/linked-fields" + }, + { + "label": "響應式", + "to": "framework/react/guides/reactivity" + }, + { + "label": "監聽器", + "to": "framework/react/guides/listeners" + }, + { + "label": "自訂錯誤", + "to": "framework/react/guides/custom-errors" + }, + { + "label": "提交處理", + "to": "framework/react/guides/submission-handling" + }, + { + "label": "UI 函式庫", + "to": "framework/react/guides/ui-libraries" + }, + { + "label": "表單組合", + "to": "framework/react/guides/form-composition" + }, + { + "label": "React Native", + "to": "framework/react/guides/react-native" + }, + { + "label": "伺服器渲染 (SSR)/TanStack Start/Next.js", + "to": "framework/react/guides/ssr" + }, + { + "label": "除錯", + "to": "framework/react/guides/debugging" + } + ] + }, + { + "label": "vue", + "children": [ + { + "label": "基本概念", + "to": "framework/vue/guides/basic-concepts" + }, + { + "label": "表單驗證", + "to": "framework/vue/guides/validation" + }, + { + "label": "非同步初始值", + "to": "framework/vue/guides/async-initial-values" + }, + { + "label": "陣列", + "to": "framework/vue/guides/arrays" + }, + { + "label": "關聯欄位", + "to": "framework/vue/guides/linked-fields" + } + ] + }, + { + "label": "angular", + "children": [ + { + "label": "基本概念", + "to": "framework/angular/guides/basic-concepts" + }, + { + "label": "表單驗證", + "to": "framework/angular/guides/validation" + }, + { + "label": "陣列", + "to": "framework/angular/guides/arrays" + } + ] + }, + { + "label": "solid", + "children": [ + { + "label": "基本概念", + "to": "framework/solid/guides/basic-concepts" + }, + { + "label": "表單驗證", + "to": "framework/solid/guides/validation" + }, + { + "label": "非同步初始值", + "to": "framework/solid/guides/async-initial-values" + }, + { + "label": "陣列", + "to": "framework/solid/guides/arrays" + }, + { + "label": "關聯欄位", + "to": "framework/solid/guides/linked-fields" + } + ] + }, + { + "label": "lit", + "children": [ + { + "label": "基本概念", + "to": "framework/lit/guides/basic-concepts" + }, + { + "label": "陣列", + "to": "framework/lit/guides/arrays" + } + ] + }, + { + "label": "svelte", + "children": [ + { + "label": "基本概念", + "to": "framework/svelte/guides/basic-concepts" + }, + { + "label": "表單驗證", + "to": "framework/svelte/guides/validation" + }, + { + "label": "非同步初始值", + "to": "framework/svelte/guides/async-initial-values" + }, + { + "label": "陣列", + "to": "framework/svelte/guides/arrays" + }, + { + "label": "關聯欄位", + "to": "framework/svelte/guides/linked-fields" + } + ] + } + ] + }, + { + "collapsible": true, + "defaultCollapsed": true, + "label": "API 參考", + "children": [ + { + "label": "JavaScript 參考", + "to": "reference/index" + }, + { + "label": "類別 / FieldApi", + "to": "reference/classes/fieldapi" + }, + { + "label": "類別 / FormApi", + "to": "reference/classes/formapi" + }, + { + "label": "函式 / formOptions", + "to": "reference/functions/formoptions" + }, + { + "label": "函式 / mergeForm", + "to": "reference/functions/mergeform" + }, + { + "label": "介面 / FieldApiOptions", + "to": "reference/interfaces/fieldapioptions" + }, + { + "label": "介面 / FieldOptions", + "to": "reference/interfaces/fieldoptions" + }, + { + "label": "介面 / FieldValidators", + "to": "reference/interfaces/fieldvalidators" + }, + { + "label": "介面 / FormOptions", + "to": "reference/interfaces/formoptions" + }, + { + "label": "介面 / FormValidators", + "to": "reference/interfaces/formvalidators" + }, + { + "label": "類型 / DeepKeys", + "to": "reference/type-aliases/deepkeys" + }, + { + "label": "類型 / DeepValue", + "to": "reference/type-aliases/deepvalue" + }, + { + "label": "類型 / FieldInfo", + "to": "reference/type-aliases/fieldinfo" + }, + { + "label": "類型 / FieldMeta", + "to": "reference/type-aliases/fieldmeta" + }, + { + "label": "類型 / FieldState", + "to": "reference/type-aliases/fieldstate" + }, + { + "label": "類型 / BaseFormState", + "to": "reference/type-aliases/baseformstate" + }, + { + "label": "類型 / DerivedFormState", + "to": "reference/type-aliases/derivedformstate" + }, + { + "label": "類型 / Updater", + "to": "reference/type-aliases/updater" + }, + { + "label": "類型 / UpdaterFn", + "to": "reference/type-aliases/updaterfn" + }, + { + "label": "類型 / ValidationError", + "to": "reference/type-aliases/validationerror" + }, + { + "label": "類型 / ValidationMeta", + "to": "reference/type-aliases/validationmeta" + } + ], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "React 參考", + "to": "framework/react/reference/index" + }, + { + "label": "函式 / Field", + "to": "framework/react/reference/functions/field" + }, + { + "label": "函式 / useField", + "to": "framework/react/reference/functions/usefield" + }, + { + "label": "函式 / useForm", + "to": "framework/react/reference/functions/useform" + }, + { + "label": "函式 / useTransform", + "to": "framework/react/reference/functions/usetransform" + }, + { + "label": "類型 / FieldComponent", + "to": "framework/react/reference/type-aliases/fieldcomponent" + }, + { + "label": "類型 / UseField", + "to": "framework/react/reference/type-aliases/usefield" + } + ] + }, + { + "label": "vue", + "children": [ + { + "label": "Vue 參考", + "to": "framework/vue/reference/index" + }, + { + "label": "函式 / Field", + "to": "framework/vue/reference/functions/field" + }, + { + "label": "函式 / useField", + "to": "framework/vue/reference/functions/usefield" + }, + { + "label": "函式 / useForm", + "to": "framework/vue/reference/functions/useform" + }, + { + "label": "類型 / FieldComponent", + "to": "framework/vue/reference/type-aliases/fieldcomponent" + }, + { + "label": "類型 / UseField", + "to": "framework/vue/reference/type-aliases/usefield" + } + ] + }, + { + "label": "solid", + "children": [ + { + "label": "Solid 參考", + "to": "framework/solid/reference/index" + }, + { + "label": "函式 / createField", + "to": "framework/solid/reference/functions/createfield" + }, + { + "label": "函式 / createForm", + "to": "framework/solid/reference/functions/createform" + }, + { + "label": "函式 / Field", + "to": "framework/solid/reference/functions/field" + }, + { + "label": "類型 / CreateField", + "to": "framework/solid/reference/type-aliases/createfield" + }, + { + "label": "類型 / FieldComponent", + "to": "framework/solid/reference/type-aliases/fieldcomponent" + } + ] + }, + { + "label": "lit", + "children": [ + { + "label": "Lit 參考", + "to": "framework/lit/reference/index" + }, + { + "label": "類別 / TanStackFormController", + "to": "framework/lit/reference/tanstackformcontroller" + } + ] + }, + { + "label": "angular", + "children": [ + { + "label": "Angular 參考", + "to": "framework/angular/reference/index" + }, + { + "label": "類別 / TanStackField", + "to": "framework/angular/reference/classes/tanstackfield" + }, + { + "label": "函式 / injectForm", + "to": "framework/angular/reference/functions/injectform" + }, + { + "label": "函式 / injectStore", + "to": "framework/angular/reference/functions/injectstore" + } + ] + } + ] + }, + { + "label": "社群資源", + "children": [], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "Balastrong 教學", + "to": "framework/react/community/balastrong-tutorial" + } + ] + } + ] + }, + { + "label": "範例", + "children": [], + "frameworks": [ + { + "label": "react", + "children": [ + { + "label": "簡單範例", + "to": "framework/react/examples/simple" + }, + { + "label": "陣列範例", + "to": "framework/react/examples/array" + }, + { + "label": "表單組合範例", + "to": "framework/react/examples/large-form" + }, + { + "label": "TanStack Query 整合範例", + "to": "framework/react/examples/query-integration" + }, + { + "label": "標準結構範例", + "to": "framework/react/examples/standard-schema" + }, + { + "label": "TanStack Start 範例", + "to": "framework/react/examples/tanstack-start" + }, + { + "label": "Next 伺服器動作範例", + "to": "framework/react/examples/next-server-actions" + }, + { + "label": "Remix 範例", + "to": "framework/react/examples/remix" + }, + { + "label": "UI 函式庫範例", + "to": "framework/react/examples/ui-libraries" + }, + { + "label": "表單驗證器欄位錯誤範例", + "to": "framework/react/examples/field-errors-from-form-validators" + } + ] + }, + { + "label": "vue", + "children": [ + { + "label": "簡單範例", + "to": "framework/vue/examples/simple" + }, + { + "label": "陣列範例", + "to": "framework/vue/examples/array" + } + ] + }, + { + "label": "angular", + "children": [ + { + "label": "簡單範例", + "to": "framework/angular/examples/simple" + }, + { + "label": "陣列範例", + "to": "framework/angular/examples/array" + } + ] + }, + { + "label": "solid", + "children": [ + { + "label": "簡單範例", + "to": "framework/solid/examples/simple" + }, + { + "label": "陣列範例", + "to": "framework/solid/examples/array" + } + ] + }, + { + "label": "lit", + "children": [ + { + "label": "簡單範例", + "to": "framework/lit/examples/simple" + }, + { + "label": "UI 函式庫範例", + "to": "framework/lit/examples/ui-libraries" + } + ] + }, + { + "label": "svelte", + "children": [ + { + "label": "簡單範例", + "to": "framework/svelte/examples/simple" + }, + { + "label": "陣列範例", + "to": "framework/svelte/examples/array" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/docs/zh-hant/framework/angular/guides/validation.md b/docs/zh-hant/framework/angular/guides/validation.md new file mode 100644 index 000000000..ce14376fe --- /dev/null +++ b/docs/zh-hant/framework/angular/guides/validation.md @@ -0,0 +1,542 @@ +--- +source-updated-at: '2025-04-16T14:15:06.000Z' +translation-updated-at: '2025-04-25T20:47:24.792Z' +id: form-validation +title: 表單驗證 +--- +TanStack Form 的核心功能之一就是驗證 (validation) 概念。TanStack Form 讓驗證變得高度可自訂: + +- 您可以控制何時執行驗證(變更時、輸入時、失焦時、提交時...) +- 驗證規則可以在欄位 (field) 層級或表單 (form) 層級定義 +- 驗證可以是同步或非同步的(例如 API 呼叫的結果) + +## 驗證何時執行? + +由您決定!`[tanstackField]` 指令接受一些回調函式作為 props,例如 `onChange` 或 `onBlur`。這些回調函式會接收欄位的當前值以及 fieldAPI 物件,讓您可以執行驗證。如果發現驗證錯誤,只需將錯誤訊息作為字串返回,它就會出現在 `field.api.state.meta.errors` 中。 + +以下是一個範例: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + @if (age.api.state.meta.errors) { + {{ age.api.state.meta.errors.join(', ') }} + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + // ... +} +``` + +在上面的範例中,驗證在每次按鍵時執行 (`onChange`)。如果我們希望驗證在欄位失焦時執行,可以這樣修改程式碼: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + + + @if (age.api.state.meta.errors) { + {{ age.api.state.meta.errors.join(', ') }} + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + // ... +} +``` + +因此,您可以透過實作所需的回調函式來控制驗證的執行時機。您甚至可以在不同時間執行不同的驗證: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + + + @if (age.api.state.meta.errors) { + {{ age.api.state.meta.errors.join(', ') }} + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + minimumAgeValidator: FieldValidateFn = ({ + value, + }) => (value < 0 ? 'Invalid value' : undefined) + + // ... +} +``` + +在上面的範例中,我們對同一個欄位在不同時間(每次按鍵和欄位失焦時)驗證不同內容。由於 `field.state.meta.errors` 是一個陣列,所有相關錯誤都會在給定時間顯示。您也可以使用 `field.state.meta.errorMap` 根據驗證執行時機(onChange、onBlur 等)取得錯誤。更多關於顯示錯誤的資訊如下。 + +## 顯示錯誤 + +設定好驗證後,您可以將錯誤從陣列映射到 UI 中顯示: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + @if (age.api.state.meta.errors) { + {{ age.api.state.meta.errors.join(', ') }} + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + // ... +} +``` + +或使用 `errorMap` 屬性來存取特定錯誤: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + @if (age.api.state.meta.errorMap['onChange']) { + {{ age.api.state.meta.errorMap['onChange'] }} + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + // ... +} +``` + +值得一提的是,我們的 `errors` 陣列和 `errorMap` 會匹配驗證器返回的類型。這意味著: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + + @if (!age.api.state.meta.errorMap['onChange']?.isOldEnough) { + The user is not old enough + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be 13 to make an account' : undefined + + // ... +} +``` + +## 欄位層級與表單層級的驗證 + +如上所示,每個 `[tanstackField]` 透過 `onChange`、`onBlur` 等回調函式接受自己的驗證規則。也可以透過將類似的回調函式傳遞給 `injectForm()` 函式,在表單層級(而不是逐個欄位)定義驗證規則。 + +範例: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` +
+ + + @if (formErrorMap().onChange) { +
+ There was an error on the form: {{ formErrorMap().onChange }} +
+ } + +
+
+ `, +}) +export class AppComponent { + form = injectForm({ + defaultValues: { + age: 0, + }, + onSubmit({ value }) { + console.log(value) + }, + validators: { + // 以與欄位相同的方式向表單添加驗證器 + onChange({ value }) { + if (value.age < 13) { + return 'Must be 13 or older to sign' + } + return undefined + }, + }, + }) + + // 訂閱表單的 errorMap,以便更新時重新渲染 + formErrorMap = injectStore(this.form, (state) => state.errorMap) +} +``` + +## 非同步函式驗證 + +雖然我們認為大多數驗證會是同步的,但在許多情況下,透過網路呼叫或其他非同步操作進行驗證會很有用。 + +為此,我們提供了專用的 `onChangeAsync`、`onBlurAsync` 等方法: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + @if (age.api.state.meta.errors) { + {{ age.api.state.meta.errors.join(', ') }} + } + + `, +}) +export class AppComponent { + ageValidator: FieldValidateAsyncFn = async ({ + value, + }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value < 13 ? 'You must be 13 to make an account' : undefined + } + + // ... +} +``` + +同步和非同步驗證可以共存。例如,可以在同一個欄位上定義 `onBlur` 和 `onBlurAsync`: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + @if (age.api.state.meta.errors) { + {{ age.api.state.meta.errors.join(', ') }} + } + + `, +}) +export class AppComponent { + ensureAge13: FieldValidateFn = ({ value }) => + value < 13 ? 'You must be at least 13' : undefined + + ensureOlderAge: FieldValidateAsyncFn = async ({ + value, + }) => { + const currentAge = await fetchCurrentAgeOnProfile() + return value < currentAge ? 'You can only increase the age' : undefined + } + + // ... +} +``` + +同步驗證方法 (`onBlur`) 會先執行,非同步方法 (`onBlurAsync`) 只有在同步方法 (`onBlur`) 成功時才會執行。要改變此行為,請將 `asyncAlways` 選項設為 `true`,這樣無論同步方法的結果如何,非同步方法都會執行。 + +### 內建防抖 (Debouncing) + +雖然非同步呼叫是針對資料庫進行驗證的方式,但在每次按鍵時發送網路請求很容易導致資料庫遭受 DDoS 攻擊。 + +相反地,我們提供了一個簡單的方法來防抖您的 `async` 呼叫,只需添加一個屬性: + +```angular-html + + + +``` + +這將對每個非同步呼叫進行 500 毫秒的防抖處理。您甚至可以針對每個驗證屬性覆寫此設定: + +```angular-html + + + +``` + +> 這將每 1500 毫秒執行一次 `onChangeAsync`,而 `onBlurAsync` 將每 500 毫秒執行一次。 + +## 透過結構描述 (Schema) 函式庫進行驗證 + +雖然函式提供了更多彈性和自訂驗證的方式,但它們可能有點冗長。為了解決這個問題,有一些函式庫提供了基於結構描述的驗證,使簡寫和類型嚴格的驗證變得更加容易。您還可以為整個表單定義一個結構描述並將其傳遞到表單層級,錯誤會自動傳播到欄位。 + +### 標準結構描述函式庫 + +TanStack Form 原生支援所有遵循 [Standard Schema 規範](https://github.com/standard-schema/standard-schema) 的函式庫,最著名的包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +_注意:_ 請確保使用結構描述函式庫的最新版本,因為舊版本可能尚未支援 Standard Schema。 + +要使用這些函式庫的結構描述,您可以像自訂函式一樣將它們傳遞給 `validators` props: + +```angular-ts +import { z } from 'zod' + +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + `, +}) +export class AppComponent { + form = injectForm({ + // ... + }) + + z = z + + // ... +} +``` + +表單和欄位層級的非同步驗證也同樣支援: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + `, +}) +export class AppComponent { + increaseAge = z.number().refine( + async (value) => { + const currentAge = await fetchCurrentAgeOnProfile() + return value >= currentAge + }, + { + message: 'You can only increase the age', + }, + ) + + // ... +} +``` + +如果您需要對 Standard Schema 驗證進行更多控制,可以像這樣將 Standard Schema 與回調函式結合使用: + +```angular-ts +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` + + + + `, +}) +export class AppComponent { + ageValidator: FieldValidateAsyncFn = async ({ + value, + fieldApi, + }) => { + const errors = fieldApi.parseValueWithSchema( + z.number().gte(13, 'You must be 13 to make an account'), + ) + if (errors) return errors + + // 繼續進行您的驗證 + } + + // ... +} +``` + +## 防止提交無效表單 + +`onChange`、`onBlur` 等回調函式也會在提交表單時執行,如果表單無效,提交會被阻止。 + +表單狀態物件有一個 `canSubmit` 標誌,當任何欄位無效且表單已被觸碰時,該標誌為 false(即使某些欄位根據其 `onChange`/`onBlur` props「技術上」無效,`canSubmit` 在表單被觸碰之前仍 diff --git a/docs/zh-hant/framework/angular/quick-start.md b/docs/zh-hant/framework/angular/quick-start.md new file mode 100644 index 000000000..c2ffd4203 --- /dev/null +++ b/docs/zh-hant/framework/angular/quick-start.md @@ -0,0 +1,62 @@ +--- +source-updated-at: '2024-07-19T07:45:40.000Z' +translation-updated-at: '2025-04-25T20:31:42.999Z' +id: quick-start +title: 快速開始 +--- +## 快速開始 + +使用 TanStack Form 最基本的入門步驟是建立一個表單並添加欄位。請注意,這個範例尚未包含任何驗證或錯誤處理功能...(目前僅展示基礎用法) + +```angular-ts +import { Component } from '@angular/core' +import { bootstrapApplication } from '@angular/platform-browser' +import { TanStackField, injectForm } from '@tanstack/angular-form' + +@Component({ + selector: 'app-root', + standalone: true, + imports: [TanStackField], + template: ` +
+
+ + + + +
+ +
+ `, +}) +export class AppComponent { + form = injectForm({ + defaultValues: { + fullName: '', + }, + onSubmit({ value }) { + // Do something with form data + console.log(value) + }, + }) + + handleSubmit(event: SubmitEvent) { + event.preventDefault() + event.stopPropagation() + this.form.handleSubmit() + } +} + +bootstrapApplication(AppComponent).catch((err) => console.error(err)) +``` + +從這裡開始,您就可以開始探索 TanStack Form 的所有其他功能了! diff --git a/docs/zh-hant/framework/angular/reference/classes/tanstackfield.md b/docs/zh-hant/framework/angular/reference/classes/tanstackfield.md new file mode 100644 index 000000000..4309226a4 --- /dev/null +++ b/docs/zh-hant/framework/angular/reference/classes/tanstackfield.md @@ -0,0 +1,312 @@ +--- +source-updated-at: '2025-03-01T06:06:46.000Z' +translation-updated-at: '2025-04-25T20:56:31.560Z' +id: TanStackField +title: 類別 / TanStackField +--- +# 類別: TanStackField\ + +定義於: [tanstack-field.directive.ts:31](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L31) + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* `DeepKeys`\<`TParentData`\> + +• **TData** *繼承自* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TSubmitMeta** + +## 實作 + +- `OnInit` +- `OnChanges` +- `OnDestroy` +- `FieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> + +## 建構函式 + +### new TanStackField() + +```ts +new TanStackField(): TanStackField +``` + +#### 回傳 + +[`TanStackField`](tanstackfield.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> + +## 屬性 + +### api + +```ts +api: FieldApi; +``` + +定義於: [tanstack-field.directive.ts:129](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L129) + +*** + +### asyncAlways? + +```ts +optional asyncAlways: boolean; +``` + +定義於: [tanstack-field.directive.ts:78](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L78) + +若為 `true`,即使同步驗證期間出現錯誤,仍會執行非同步驗證。 + +#### 實作於 + +```ts +FieldOptions.asyncAlways +``` + +*** + +### asyncDebounceMs? + +```ts +optional asyncDebounceMs: number; +``` + +定義於: [tanstack-field.directive.ts:77](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L77) + +若未傳入更特定的防抖時間,則為非同步驗證的預設防抖時間。 + +#### 實作於 + +```ts +FieldOptions.asyncDebounceMs +``` + +*** + +### defaultMeta? + +```ts +optional defaultMeta: Partial>; +``` + +定義於: [tanstack-field.directive.ts:106](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L106) + +欄位的預設中繼資料物件(可選)。 + +#### 實作於 + +```ts +FieldOptions.defaultMeta +``` + +*** + +### defaultValue? + +```ts +optional defaultValue: NoInfer; +``` + +定義於: [tanstack-field.directive.ts:76](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L76) + +欄位的預設值(可選)。 + +#### 實作於 + +```ts +FieldOptions.defaultValue +``` + +*** + +### disableErrorFlat? + +```ts +optional disableErrorFlat: boolean; +``` + +定義於: [tanstack-field.directive.ts:127](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L127) + +停用 `field.errors` 上的 `flat(1)` 操作。這在您希望保持錯誤結構不變時很有用。不建議大多數使用情境使用。 + +#### 實作於 + +```ts +FieldOptions.disableErrorFlat +``` + +*** + +### listeners? + +```ts +optional listeners: NoInfer>; +``` + +定義於: [tanstack-field.directive.ts:105](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L105) + +附加到相應事件的監聽器列表 + +#### 實作於 + +```ts +FieldOptions.listeners +``` + +*** + +### name + +```ts +name: TName; +``` + +定義於: [tanstack-field.directive.ts:75](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L75) + +欄位名稱。型別為 `DeepKeys`,以確保您的名稱是父資料集的深層鍵。 + +#### 實作於 + +```ts +FieldOptions.name +``` + +*** + +### tanstackField + +```ts +tanstackField: FormApi; +``` + +定義於: [tanstack-field.directive.ts:79](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L79) + +*** + +### unmount()? + +```ts +optional unmount: () => void; +``` + +定義於: [tanstack-field.directive.ts:185](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L185) + +#### 回傳 + +`void` + +*** + +### validators? + +```ts +optional validators: NoInfer>; +``` + +定義於: [tanstack-field.directive.ts:91](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L91) + +傳遞給欄位的驗證器列表 + +#### 實作於 + +```ts +FieldOptions.validators +``` + +## 方法 + +### ngOnChanges() + +```ts +ngOnChanges(): void +``` + +定義於: [tanstack-field.directive.ts:197](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L197) + +一個回呼方法,在預設變更檢測器檢查資料綁定屬性(若至少有一個已變更)後立即呼叫,並在檢查視圖和內容子項之前呼叫。 + +#### 回傳 + +`void` + +#### 實作於 + +```ts +OnChanges.ngOnChanges +``` + +*** + +### ngOnDestroy() + +```ts +ngOnDestroy(): void +``` + +定義於: [tanstack-field.directive.ts:193](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L193) + +一個執行自訂清理的回呼方法,在指令、管道或服務實例被銷毀前立即呼叫。 + +#### 回傳 + +`void` + +#### 實作於 + +```ts +OnDestroy.ngOnDestroy +``` + +*** + +### ngOnInit() + +```ts +ngOnInit(): void +``` + +定義於: [tanstack-field.directive.ts:187](https://github.com/TanStack/form/blob/main/packages/angular-form/src/tanstack-field.directive.ts#L187) + +一個回呼方法,在預設變更檢測器首次檢查指令的資料綁定屬性後立即呼叫,並在檢查任何視圖或內容子項之前呼叫。僅在指令實例化時呼叫一次。 + +#### 回傳 + +`void` + +#### 實作於 + +```ts +OnInit.ngOnInit +``` diff --git a/docs/zh-hant/framework/angular/reference/functions/injectform.md b/docs/zh-hant/framework/angular/reference/functions/injectform.md new file mode 100644 index 000000000..42f1c8e99 --- /dev/null +++ b/docs/zh-hant/framework/angular/reference/functions/injectform.md @@ -0,0 +1,47 @@ +--- +source-updated-at: '2025-02-25T06:59:48.000Z' +translation-updated-at: '2025-04-25T20:55:07.916Z' +id: injectForm +title: 函式 / injectForm +--- + + +# 函式: injectForm() + +```ts +function injectForm(opts?): FormApi +``` + +定義於: [inject-form.ts:9](https://github.com/TanStack/form/blob/main/packages/angular-form/src/inject-form.ts#L9) + +## 類型參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TSubmitMeta** + +## 參數 + +### opts? + +`FormOptions`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +## 回傳值 + +`FormApi`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> diff --git a/docs/zh-hant/framework/angular/reference/functions/injectstore.md b/docs/zh-hant/framework/angular/reference/functions/injectstore.md new file mode 100644 index 000000000..9684ef48a --- /dev/null +++ b/docs/zh-hant/framework/angular/reference/functions/injectstore.md @@ -0,0 +1,53 @@ +--- +source-updated-at: '2025-02-25T06:59:48.000Z' +translation-updated-at: '2025-04-25T20:55:08.950Z' +id: injectStore +title: 函式 / injectStore +--- + + +# 函式: injectStore() + +```ts +function injectStore(form, selector?): Signal +``` + +定義於: [inject-store.ts:9](https://github.com/TanStack/form/blob/main/packages/angular-form/src/inject-store.ts#L9) + +## 類型參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TSubmitMeta** + +• **TSelected** = `NoInfer`\<`FormState`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\>\> + +## 參數 + +### form + +`FormApi`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +### selector? + +(`state`) => `TSelected` + +## 回傳值 + +`Signal`\<`TSelected`\> diff --git a/docs/zh-hant/framework/angular/reference/index.md b/docs/zh-hant/framework/angular/reference/index.md new file mode 100644 index 000000000..2fc65ef79 --- /dev/null +++ b/docs/zh-hant/framework/angular/reference/index.md @@ -0,0 +1,18 @@ +--- +source-updated-at: '2025-02-22T01:19:17.000Z' +translation-updated-at: '2025-04-25T20:54:29.312Z' +id: '@tanstack/angular-form' +title: Angular 參考 +--- + + +# @tanstack/angular-form + +## 類別 (Classes) + +- [TanStackField](classes/tanstackfield.md) + +## 函式 (Functions) + +- [injectForm](functions/injectform.md) +- [injectStore](functions/injectstore.md) diff --git a/docs/zh-hant/framework/lit/guides/arrays.md b/docs/zh-hant/framework/lit/guides/arrays.md new file mode 100644 index 000000000..e63fc272c --- /dev/null +++ b/docs/zh-hant/framework/lit/guides/arrays.md @@ -0,0 +1,175 @@ +--- +source-updated-at: '2025-03-28T15:34:36.000Z' +translation-updated-at: '2025-04-25T20:47:51.581Z' +id: arrays +title: 陣列 +--- +TanStack Form 支援將陣列 (array) 作為表單值使用,包含陣列中的子物件值。 + +## 基本用法 + +要使用陣列,你可以對陣列值使用 `field.state.value`,如下所示: + +```ts +export class TestForm extends LitElement { + #form = new TanStackFormController(this, { + defaultValues: { + people: [] as Array<{ name: string; age: string }>, + }, + }) + render() { + return html` +
{ + e.preventDefault() + }} + > +

請輸入您的詳細資料

+ ${this.#form.field( + { + name: `people`, + }, + (peopleField) => { + return html`${repeat( + peopleField.state.value, + (_, index) => index, + (_, index) => { + return html` // ... ` + }, + )} ` + }, + )} +
+ ` + } +} +``` + +這會在每次對欄位執行 pushValue 時生成對應的 HTML: + +```html +
+ +
+``` + +最後,你可以像這樣使用子欄位 (subfield): + +```ts +return html` + ${this.#form.field( + { + name: `people[${index}].name`, + }, + (field) => { + return html` + + ` + }, + )} +` +``` + +## 完整範例 + +```typescript +export class TestForm extends LitElement { + #form = new TanStackFormController(this, { + defaultValues: { + people: [] as Array<{ name: string}>, + }, + }); + render() { + return html` +
{ + e.preventDefault(); + }} + > +

請輸入您的詳細資料

+ ${this.#form.field( + { + name: `people`, + }, + (peopleField) => { + return html`${repeat( + peopleField.state.value, + (_, index) => index, + (_, index) => { + return html` + ${this.#form.field( + { + name: `people[${index}].name`, + }, + (field) => { + return html`
+
+ + +
+
`; + } + )} + `; + } + )} + +
+ +
`; + } + )} + +
+ + +
+
+ `; + } + +declare global { + interface HTMLElementTagNameMap { + "test-form": TestForm; + } +} +``` diff --git a/docs/zh-hant/framework/lit/guides/basic-concepts.md b/docs/zh-hant/framework/lit/guides/basic-concepts.md new file mode 100644 index 000000000..d69ae3290 --- /dev/null +++ b/docs/zh-hant/framework/lit/guides/basic-concepts.md @@ -0,0 +1,103 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:47:50.231Z' +id: basic-concepts +title: 基本概念 +--- +本頁介紹 `@tanstack/lit-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更好地理解並運用該函式庫及其與 Lit 的整合方式。 + +## 表單選項 (Form Options) + +您可以使用 `formOptions` 函式建立表單選項,以便在多個表單之間共享配置。 + +範例: + +```tsx +const formOpts = formOptions({ + defaultValues: { + firstName: '', + lastName: '', + employed: false, + jobTitle: '', + } as Employee, +}) +``` + +## 表單實例 (Form Instance) + +表單實例是一個代表單一表單的物件,提供操作表單的方法與屬性。您可以使用 `@tanstack/lit-form` 提供的 `TanStackFormController` 介面來建立表單實例。`TanStackFormController` 會以當前表單所屬的類別 (`this`) 與預設表單選項進行實例化,負責初始化表單狀態、處理表單提交,並提供管理表單欄位及其驗證的方法。 + +```tsx +#form = new TanStackFormController(this, { + defaultValues: { + firstName: '', + lastName: '', + employed: false, + jobTitle: '', + } as Employee, +}) +``` + +您也可以不使用 `formOptions`,直接透過獨立的 `TanStackFormController` API 建立表單實例: + +```tsx +#form = new TanStackFormController(this, { + ...formOpts, +}) +``` + +## 欄位 (Field) + +欄位代表單一表單輸入元素,例如文字輸入框或核取方塊。欄位是透過表單實例提供的 `field(FieldOptions, callback)` 方法建立。該元件接受一個 `FieldOptions` 物件與回呼函式,回呼函式會收到一個 `FieldApi` 物件,該物件提供取得欄位當前值、處理輸入變更與處理模糊事件的方法。 + +範例: + +```ts + ${this.#form.field( + { + name: `firstName`, + validators: { + onChange: ({ value }) => + value.length < 3 ? "Not long enough" : undefined, + }, + }, + (field: FieldApi) => { + return html`
+ + +
`; + }, +)} +``` + +## 欄位狀態 (Field State) + +每個欄位都有自身的狀態,包含當前值、驗證狀態、錯誤訊息與其他元資料。您可以透過欄位的 `field.state` 屬性存取其狀態。 + +```tsx +const { + value, + meta: { errors, isValidating }, +} = field.state +``` + +有三種欄位狀態對於觀察使用者互動非常有用:當使用者點擊/切換至欄位時,欄位會被標記為 _"touched"_;在值被修改前保持 _"pristine"_;值變更後則標記為 _"dirty"_。您可以透過以下所示的 `isTouched`、`isPristine` 與 `isDirty` 標記來檢查這些狀態。 + +```tsx +const { isTouched, isPristine, isDirty } = field.state.meta +``` + +![欄位狀態](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/field-states.png) diff --git a/docs/zh-hant/framework/lit/quick-start.md b/docs/zh-hant/framework/lit/quick-start.md new file mode 100644 index 000000000..d9c044c16 --- /dev/null +++ b/docs/zh-hant/framework/lit/quick-start.md @@ -0,0 +1,85 @@ +--- +source-updated-at: '2025-03-01T08:30:20.000Z' +translation-updated-at: '2025-04-25T20:31:47.922Z' +id: quick-start +title: 快速開始 +--- +## 快速開始 + +使用 TanStack Form 的最低要求是建立一個 `TanstackFormController`,如下所示,並使用 `Employee` 介面作為測試表單的結構: + +```ts +interface Employee { + firstName: string + lastName: string + employed: boolean + jobTitle: string +} + +#form = new TanStackFormController()(this, { + defaultValues: { + firstName: '', + lastName: '', + employed: false, + jobTitle: '', + }, +}) +``` + +在此範例中,`this` 參照了您想要使用 TanStack Form 的 `LitElement` 實例。 + +要將模板中的表單元素與 TanStack Form 連接,請使用 `TanstackFormController` 的 `field` 方法。 + +`field` 的第一個參數是 `FieldOptions`,第二個參數是用於渲染元素的回呼函式。 + +```ts +field(FieldOptions, callback) +``` + +完成的測試表單應如下所示。該表單會從使用者輸入欄位收集名字: + +```ts +export class TestForm extends LitElement { + #form = new TanStackFormController(this, { + defaultValues: { + firstName: '', + lastName: '', + employed: false, + jobTitle: '', + }, + }) + render() { + return html`

請輸入您的名字>

+ ${this.#form.field( + { + name: `firstName`, + validators: { + onChange: ({ value }) => + value.length < 3 ? '長度不足' : undefined, + }, + }, + (field: FieldApi) => { + return html`
+ + +
` + }, + )}` + } +} +``` + +請注意,您需要自行處理元素和表單的更新,如上例所示。 diff --git a/docs/zh-hant/framework/lit/reference/index.md b/docs/zh-hant/framework/lit/reference/index.md new file mode 100644 index 000000000..ee263777f --- /dev/null +++ b/docs/zh-hant/framework/lit/reference/index.md @@ -0,0 +1,13 @@ +--- +source-updated-at: '2025-02-22T01:19:17.000Z' +translation-updated-at: '2025-04-25T20:54:28.114Z' +id: '@tanstack/lit-form' +title: Lit 參考 +--- + + +# @tanstack/lit-form + +## 類別 + +- [TanStackFormController](classes/tanstackformcontroller.md) diff --git a/docs/zh-hant/framework/react/community/balastrong-tutorial.md b/docs/zh-hant/framework/react/community/balastrong-tutorial.md new file mode 100644 index 000000000..4dd3271ec --- /dev/null +++ b/docs/zh-hant/framework/react/community/balastrong-tutorial.md @@ -0,0 +1,37 @@ +--- +source-updated-at: '2025-03-15T14:42:04.000Z' +translation-updated-at: '2025-04-25T20:55:12.761Z' +id: balastrong-tutorial +title: Balastrong 教學 +--- +TanStack Form 的維護者 [Balastrong](https://bsky.app/profile/leonardomontini.dev) 製作了一系列影片教學,展示該函式庫最核心的功能。您將找到逐步指南,深入了解如何使用 TanStack Form 建構功能,並獲得一些實用技巧與訣竅。 + +[觀看完整播放清單](https://www.youtube.com/playlist?list=PLOQjd5dsGSxInTKUWTxyqSKwZCjDIUs0Y) + +## 1. [設定與驗證](https://youtu.be/Pf1qn35bgjs) + +學習 TanStack Form 的第一步,從函式庫設定到建立包含文字欄位與驗證(同步、防抖動與非同步)的簡單表單。[觀看影片 (8:16)](https://youtu.be/Pf1qn35bgjs) + +## 2. [進階驗證](https://youtu.be/Pys2ExswZT0) + +展示如何透過後端 API 驗證資料,同時透過控制載入狀態、錯誤訊息與關聯欄位來確保流暢的使用者體驗。[觀看影片 (8:05)](https://youtu.be/Pys2ExswZT0) + +## 3. [陣列欄位](https://youtu.be/0IPPHdjvrzk) + +如何處理包含基本型別(字串、數字)與物件(巢狀欄位)的陣列欄位,包括驗證與重新排序。[觀看影片 (6:53)](https://youtu.be/0IPPHdjvrzk) + +## 4. [響應式](https://youtu.be/UXRZvNCnE-s) + +了解表單值為何不會即時更新、這種行為的設計意圖,以及如何有效觸發 UI 更新。[觀看影片 (4:26)](https://youtu.be/UXRZvNCnE-s) + +## 5. [使用結構描述函式庫進行表單驗證](https://youtu.be/HSboMHfPuZA) + +使用 zod、yup 或 valibot 等結構描述函式庫定義驗證規則,並透過轉接器傳遞給 TanStack Form 以一次性驗證所有欄位。[觀看影片 (6:29)](https://youtu.be/HSboMHfPuZA) + +## 6. [副作用與監聽器](https://youtu.be/A-w2IG7DAso) + +類似欄位驗證器,您可以為欄位監聽器附加事件並作出反應,例如在相依欄位變更時重設特定欄位。[觀看影片 (5:50)](https://youtu.be/A-w2IG7DAso) + +## 7. [大型表單的可組合欄位](https://youtu.be/YJ3rW85fnKo) + +透過組合式 API,您可以建立可重複使用的元件,預先綁定並連接到通用表單上下文,大幅減少應用程式中所有表單實例的重複程式碼。這對於包含大量欄位的大型表單特別有用。[觀看影片 (11:01)](https://youtu.be/YJ3rW85fnKo) diff --git a/docs/zh-hant/framework/react/guides/arrays.md b/docs/zh-hant/framework/react/guides/arrays.md new file mode 100644 index 000000000..6bcbc9778 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/arrays.md @@ -0,0 +1,125 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:33:38.845Z' +id: arrays +title: 陣列 +--- +TanStack Form 支援將陣列 (array) 作為表單值使用,包括陣列中的子物件值。 + +## 基本用法 + +要使用陣列,可以在陣列值上使用 `field.state.value`: + +```jsx +function App() { + const form = useForm({ + defaultValues: { + people: [], + }, + }) + + return ( + + {(field) => ( +
+ {field.state.value.map((_, i) => { + // ... + })} +
+ )} +
+ ) +} +``` + +每次在 `field` 上執行 `pushValue` 時,都會生成對應的 JSX: + +```jsx + +``` + +最後,可以像這樣使用子欄位 (subfield): + +```jsx + + {(subField) => ( + subField.handleChange(e.target.value)} + /> + )} + +``` + +## 完整範例 + +```jsx +function App() { + const form = useForm({ + defaultValues: { + people: [], + }, + onSubmit({ value }) { + alert(JSON.stringify(value)) + }, + }) + + return ( +
+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > + + {(field) => { + return ( +
+ {field.state.value.map((_, i) => { + return ( + + {(subField) => { + return ( +
+ +
+ ) + }} +
+ ) + })} + +
+ ) + }} +
+ [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + + )} + /> + +
+ ) +} +``` diff --git a/docs/zh-hant/framework/react/guides/async-initial-values.md b/docs/zh-hant/framework/react/guides/async-initial-values.md new file mode 100644 index 000000000..a6f848031 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/async-initial-values.md @@ -0,0 +1,51 @@ +--- +source-updated-at: '2025-03-28T15:34:36.000Z' +translation-updated-at: '2025-04-25T20:33:29.078Z' +id: async-initial-values +title: 非同步初始值 +--- +假設您想從 API 獲取一些資料,並將其作為表單的初始值使用。 + +雖然這個問題表面上看起來很簡單,但背後可能隱藏著您尚未考慮到的複雜性。 + +舉例來說,您可能希望在資料獲取期間顯示載入動畫,或是優雅地處理錯誤情況。同樣地,您也可能會尋找快取資料的方法,以避免每次渲染表單時都需要重新獲取資料。 + +雖然我們可以從頭實作這些功能,但最終結果可能會與我們維護的另一個專案 [TanStack Query](https://tanstack.com/query) 非常相似。 + +因此,本指南將向您展示如何結合使用 TanStack Form 與 TanStack Query 來實現所需行為。 + +## 基本用法 + +```tsx +import { useForm } from '@tanstack/react-form' +import { useQuery } from '@tanstack/react-query' + +export default function App() { + const {data, isLoading} = useQuery({ + queryKey: ['data'], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return {firstName: 'FirstName', lastName: "LastName"} + } + }) + + const form = useForm({ + defaultValues: { + firstName: data?.firstName ?? '', + lastName: data?.lastName ?? '', + }, + onSubmit: async ({ value }) => { + // Do something with form data + console.log(value) + }, + }) + + if (isLoading) return

Loading..

+ + return ( + // ... + ) +} +``` + +這段程式碼會在資料獲取完成前顯示載入提示,然後使用獲取到的資料作為初始值來渲染表單。 diff --git a/docs/zh-hant/framework/react/guides/basic-concepts.md b/docs/zh-hant/framework/react/guides/basic-concepts.md new file mode 100644 index 000000000..976179597 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/basic-concepts.md @@ -0,0 +1,361 @@ +--- +source-updated-at: '2025-04-16T08:45:06.000Z' +translation-updated-at: '2025-04-25T20:33:31.771Z' +id: basic-concepts +title: 基本概念 +--- +本頁介紹 `@tanstack/react-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更有效地理解並運用此函式庫。 + +## 表單選項 (Form Options) + +您可以使用 `formOptions` 函式建立表單選項,以便在多個表單間共享設定。 + +範例: + +```tsx +interface User { + firstName: string + lastName: string + hobbies: Array +} +const defaultUser: User = { firstName: '', lastName: '', hobbies: [] } + +const formOpts = formOptions({ + defaultValues: defaultUser, +}) +``` + +## 表單實例 (Form Instance) + +表單實例是一個代表單一表單的物件,提供操作表單的方法與屬性。您可透過表單選項提供的 `useForm` 鉤子來建立表單實例。此鉤子接受包含 `onSubmit` 函式的物件,該函式會在表單提交時被呼叫。 + +```tsx +const form = useForm({ + ...formOpts, + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, +}) +``` + +您也可以不使用 `formOptions`,直接透過獨立的 `useForm` API 建立表單實例: + +```tsx +interface User { + firstName: string + lastName: string + hobbies: Array +} +const defaultUser: User = { firstName: '', lastName: '', hobbies: [] } + +const form = useForm({ + defaultValues: defaultUser, + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, +}) +``` + +## 欄位 (Field) + +欄位代表單一表單輸入元素,例如文字輸入框或核取方塊。欄位是透過表單實例提供的 `form.Field` 元件來建立。此元件接受 `name` 屬性,需與表單預設值中的鍵名匹配,以及 `children` 屬性(這是一個接收欄位物件作為參數的渲染函式)。 + +範例: + +```tsx + ( + <> + field.handleChange(e.target.value)} + /> + + + )} +/> +``` + +## 欄位狀態 (Field State) + +每個欄位都有自身的狀態,包含當前值、驗證狀態、錯誤訊息及其他元資料。您可透過 `field.state` 屬性存取欄位狀態。 + +範例: + +```tsx +const { + value, + meta: { errors, isValidating }, +} = field.state +``` + +有三種欄位狀態有助於觀察使用者互動:當使用者點擊/切換至欄位時為「已觸碰 _(touched)_」、使用者未改變值前為「原始狀態 _(pristine)_」、值變更後則為「已修改 _(dirty)_」。可透過以下標誌檢查這些狀態: + +```tsx +const { isTouched, isPristine, isDirty } = field.state.meta +``` + +![欄位狀態](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/field-states.png) + +> **給從 `React Hook Form` 轉換的使用者重要提示**:`TanStack/form` 中的 `isDirty` 標誌與 RHF 中同名的標誌意義不同。 +> 在 RHF 中,當表單值與原始值不同時 `isDirty = true`。若使用者修改表單值後又改回與預設值相同,RHF 的 `isDirty` 會是 `false`,但在 `TanStack/form` 中會是 `true`。 +> `TanStack/form` 同時在表單與欄位層級暴露預設值 (`form.options.defaultValues`, `field.options.defaultValue`),因此若需模擬 RHF 的行為,您可以自行編寫 `isDefaultValue()` 輔助函式。 + +## 欄位 API (Field API) + +欄位 API 是建立欄位時傳遞給渲染函式的物件,提供操作欄位狀態的方法。 + +範例: + +```tsx + field.handleChange(e.target.value)} +/> +``` + +## 驗證 (Validation) + +`@tanstack/react-form` 原生支援同步與非同步驗證。驗證函式可透過 `validators` 屬性傳遞給 `form.Field` 元件。 + +範例: + +```tsx + + !value + ? '必須填寫名字' + : value.length < 3 + ? '名字至少需 3 個字元' + : undefined, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value.includes('error') && '名字中不得包含 "error"' + }, + }} + children={(field) => ( + <> + field.handleChange(e.target.value)} + /> + + + )} +/> +``` + +## 使用標準結構描述函式庫驗證 (Validation with Standard Schema Libraries) + +除了手動驗證選項外,我們也支援 [Standard Schema](https://github.com/standard-schema/standard-schema) 規範。 + +您可以使用任何實作此規範的函式庫定義結構描述,並將其傳遞給表單或欄位驗證器。 + +支援的函式庫包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +```tsx +import { z } from 'zod' + +const userSchema = z.object({ + age: z.number().gte(13, '必須年滿 13 歲才能建立帳戶'), +}) + +function App() { + const form = useForm({ + defaultValues: { + age: 0, + }, + validators: { + onChange: userSchema, + }, + }) + return ( +
+ { + return <>{/* ... */} + }} + /> +
+ ) +} +``` + +## 響應式 (Reactivity) + +`@tanstack/react-form` 提供多種訂閱表單與欄位狀態變更的方式,最顯著的是 `useStore(form.store)` 鉤子與 `form.Subscribe` 元件。這些方法讓您能透過僅在必要時更新元件來優化表單渲染效能。 + +範例: + +```tsx +const firstName = useStore(form.store, (state) => state.values.firstName) +//... + [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + + )} +/> +``` + +需特別注意,雖然 `useStore` 鉤子的 `selector` 屬性是可選的,但強烈建議提供此參數,因為省略它會導致不必要的重新渲染。 + +```tsx +// 正確用法 +const firstName = useStore(form.store, (state) => state.values.firstName) +const errors = useStore(form.store, (state) => state.errorMap) +// 錯誤用法 +const store = useStore(form.store) +``` + +注意:不建議使用 `useField` 鉤子來實現響應式,因為它設計上是供 `form.Field` 元件內部謹慎使用的。您應考慮改用 `useStore(form.store)`。 + +## 監聽器 (Listeners) + +`@tanstack/react-form` 允許您對特定觸發事件作出反應並「監聽」它們以執行副作用。 + +範例: + +```tsx + { + console.log(`國家已變更為: ${value}, 重置省份選項`) + form.setFieldValue('province', '') + }, + }} +/> +``` + +更多資訊請參閱 [監聽器](./listeners.md) + +## 陣列欄位 (Array Fields) + +陣列欄位讓您能管理表單中的值列表,例如興趣愛好清單。您可透過 `form.Field` 元件加上 `mode="array"` 屬性來建立陣列欄位。 + +操作陣列欄位時,可使用欄位的 `pushValue`、`removeValue`、`swapValues` 和 `moveValue` 方法來新增、移除與交換陣列中的值。 + +範例: + +```tsx + ( +
+ 興趣愛好 +
+ {!hobbiesField.state.value.length + ? '尚未新增任何興趣愛好。' + : hobbiesField.state.value.map((_, i) => ( +
+ { + return ( +
+ + field.handleChange(e.target.value)} + /> + + +
+ ) + }} + /> + { + return ( +
+ + field.handleChange(e.target.value)} + /> + +
+ ) + }} + /> +
+ ))} +
+ +
+ )} +/> +``` + +## 重設按鈕 (Reset Buttons) + +當結合使用 `} +
+ ) +} + +const { useAppForm, withForm } = createFormHook({ + fieldComponents: {}, + formComponents: { + SubscribeButton, + }, + fieldContext, + formContext, +}) + +function App() { + const form = useAppForm({ + defaultValues: { + firstName: 'John', + lastName: 'Doe', + }, + }) + + return ( + + // 注意 `AppForm` 元件包裝器;`AppForm` 提供了所需的上下文 + + + ) +} +``` + +## 將大型表單拆分為小部分 + +有時表單會變得非常大;這只是有時會發生的情況。雖然 TanStack Form 能很好地支援大型表單,但處理數百或數千行程式碼的檔案從來都不是一件有趣的事。 + +為了解決這個問題,我們支援使用 `withForm` 高階元件 (HOC) 將表單拆分為較小的部分。 + +```tsx +const { useAppForm, withForm } = createFormHook({ + fieldComponents: { + TextField, + }, + formComponents: { + SubscribeButton, + }, + fieldContext, + formContext, +}) + +const ChildForm = withForm({ + // 這些值僅用於類型檢查,不在運行時使用 + // 這允許你從 `formOptions` 中 `...formOpts` 而無需重新聲明選項 + defaultValues: { + firstName: 'John', + lastName: 'Doe', + }, + // 可選,但除了 `form` 外還為 `render` 函式添加屬性 + props: { + // 這些屬性也設置為 `render` 函式的默認值 + title: 'Child Form', + }, + render: function Render({ form, title }) { + return ( +
+

{title}

+ } + /> + + + +
+ ) + }, +}) + +function App() { + const form = useAppForm({ + defaultValues: { + firstName: 'John', + lastName: 'Doe', + }, + }) + + return +} +``` + +### `withForm` 常見問題 + +> 為什麼使用高階元件而非鉤子? + +雖然鉤子是 React 的未來,但高階元件仍然是組合的強大工具。特別是,`useForm` 的 API 使我們能夠擁有強大的類型安全性,而無需使用者傳遞泛型。 + +> 為什麼我在 `render` 中收到關於鉤子的 ESLint 錯誤? + +ESLint 在函式的頂層尋找鉤子,而 `render` 可能不會被識別為頂層元件,具體取決於你如何定義它。 + +```tsx +// 這將導致使用鉤子時出現 ESLint 錯誤 +const ChildForm = withForm({ + // ... + render: ({ form, title }) => { + // ... + }, +}) +``` + +```tsx +// 這樣可以正常工作 +const ChildForm = withForm({ + // ... + render: function Render({ form, title }) { + // ... + }, +}) +``` + +## 樹搖晃表單和欄位元件 (Tree-shaking Form and Field Components) + +雖然上述範例對於入門非常有用,但它們並不適合某些使用案例,例如你可能擁有數百個表單和欄位元件的情況。 +特別是,你可能不希望在所有使用表單鉤子的檔案的套件中包含所有的表單和欄位元件。 + +為了解決這個問題,你可以將 `createFormHook` TanStack API 與 React 的 `lazy` 和 `Suspense` 元件結合使用: + +```typescript +// src/hooks/form-context.ts +import { createFormHookContexts } from '@tanstack/react-form' + +export const { fieldContext, useFieldContext, formContext, useFormContext } = + createFormHookContexts() +``` + +```tsx +// src/components/text-field.tsx +import { useFieldContext } from '../hooks/form-context.tsx' + +export default function TextField({ label }: { label: string }) { + const field = useFieldContext() + + return ( + + ) +} +``` + +```tsx +// src/hooks/form.ts +import { lazy } from 'react' +import { createFormHook } from '@tanstack/react-form' + +const TextField = lazy(() => import('../components/text-fields.tsx')) + +const { useAppForm, withForm } = createFormHook({ + fieldContext, + formContext, + fieldComponents: { + TextField, + }, + formComponents: {}, +}) +``` + +```tsx +// src/App.tsx +import { Suspense } from 'react' +import { PeoplePage } from './features/people/page.tsx' + +export default function App() { + return ( + Loading...

}> + +
+ ) +} +``` + +這將在載入 `TextField` 元件時顯示 Suspense 回退內容,然後在載入完成後渲染表單。 + +## 綜合應用 + +現在我們已經介紹了創建自訂表單鉤子的基礎知識,讓我們將所有內容整合到一個範例中。 + +```tsx +// /src/hooks/form.ts,用於整個應用程式 +const { fieldContext, useFieldContext, formContext, useFormContext } = + createFormHookContexts() + +function TextField({ label }: { label: string }) { + const field = useFieldContext() + return ( + + ) +} + +function SubscribeButton({ label }: { label: string }) { + const form = useFormContext() + return ( + state.isSubmitting}> + {(isSubmitting) => } + + ) +} + +const { useAppForm, withForm } = createFormHook({ + fieldComponents: { + TextField, + }, + formComponents: { + SubscribeButton, + }, + fieldContext, + formContext, +}) + +// /src/features/people/shared-form.ts,用於 `people` 功能 +const formOpts = formOptions({ + defaultValues: { + firstName: 'John', + lastName: 'Doe', + }, +}) + +// /src/features/people/nested-form.ts,用於 `people` 頁面 +const ChildForm = withForm({ + ...formOpts, + // 可選,但為 `render` 函式添加 `form` 之外的屬性 + props: { + title: 'Child Form', + }, + render: ({ form, title }) => { + return ( +
+

{title}

+ } + /> + + + +
+ ) + }, +}) + +// /src/features/people/page.ts +const Parent = () => { + const form = useAppForm({ + ...formOpts, + }) + + return +} +``` + +## API 使用指南 + +以下圖表可幫助你決定應該使用哪些 API: + +![](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/react_form_composability.svg) diff --git a/docs/zh-hant/framework/react/guides/linked-fields.md b/docs/zh-hant/framework/react/guides/linked-fields.md new file mode 100644 index 000000000..d040cfc72 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/linked-fields.md @@ -0,0 +1,80 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:33:34.857Z' +id: linked-fields +title: 關聯欄位 +--- +## 連結兩個表單欄位 + +您可能會遇到需要將兩個欄位連結在一起的情況:當一個欄位驗證失敗時,另一個欄位的值已發生變化。 +其中一種常見情境是同時擁有 `password` 和 `confirm_password` 欄位時, +您會希望當 `password` 的值不匹配時,`confirm_password` 欄位顯示錯誤; +無論是哪個欄位觸發了值變更。 + +想像以下使用者流程: + +- 使用者更新確認密碼欄位 +- 使用者更新非確認密碼欄位 + +在這個範例中,表單仍會顯示錯誤, +因為「確認密碼」欄位的驗證並未重新執行以標記為已接受。 + +為了解決這個問題,我們需要確保在密碼欄位更新時重新執行「確認密碼」的驗證。 +您可以透過在 `confirm_password` 欄位添加 `onChangeListenTo` 屬性來實現。 + +```tsx +function App() { + const form = useForm({ + defaultValues: { + password: '', + confirm_password: '', + }, + // ... + }) + + return ( +
+ + {(field) => ( + + )} + + { + if (value !== fieldApi.form.getFieldValue('password')) { + return 'Passwords do not match' + } + return undefined + }, + }} + > + {(field) => ( +
+ + {field.state.meta.errors.map((err) => ( +
{err}
+ ))} +
+ )} +
+
+ ) +} +``` + +同樣地,此機制也適用於 `onBlurListenTo` 屬性,當欄位失去焦點時會重新執行驗證。 diff --git a/docs/zh-hant/framework/react/guides/listeners.md b/docs/zh-hant/framework/react/guides/listeners.md new file mode 100644 index 000000000..64ed55fe8 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/listeners.md @@ -0,0 +1,127 @@ +--- +source-updated-at: '2025-04-25T12:57:21.000Z' +translation-updated-at: '2025-04-25T20:33:46.836Z' +id: listeners +title: 監聽器 +--- +## 事件觸發的副作用 (Side effects) + +當您需要「影響」或「回應」觸發事件時,可以使用監聽器 API (listener API)。舉例來說,如果您作為開發者,想要在某個欄位變更時重置另一個表單欄位,就可以使用監聽器 API。 + +想像以下使用者流程: + +- 使用者從下拉選單中選擇國家 +- 接著從另一個下拉選單中選擇省份 +- 使用者又將選定的國家更改為其他國家 + +在這個範例中,當使用者變更國家時,已選定的省份需要被重置,因為它不再有效。透過監聽器 API,我們可以訂閱 `onChange` 事件,並在監聽器觸發時對「省份」欄位發送重置指令。 + +可監聽的事件包括: + +- `onChange` +- `onBlur` +- `onMount` +- `onSubmit` + +```tsx +function App() { + const form = useForm({ + defaultValues: { + country: '', + province: '', + }, + // ... + }) + + return ( +
+ { + console.log(`Country changed to: ${value}, resetting province`) + form.setFieldValue('province', '') + }, + }} + > + {(field) => ( + + )} + + + + {(field) => ( + + )} + +
+ ) +} +``` + +### 內建防抖動 (Debouncing) + +如果您需要在監聽器內發送 API 請求,可能會希望對呼叫進行防抖動處理,以避免效能問題。我們提供簡易的方法來實現監聽器防抖動,只需添加 `onChangeDebounceMs` 或 `onBlurDebounceMs` 參數即可。 + +```tsx + { + console.log(`Country changed to: ${value} without a change within 500ms, resetting province`) + form.setFieldValue('province', '') + }, + }} +> + {(field) => ( + /* ... */ + )} + +``` + +### 表單層級監聽器 + +在更高層級的表單層面也提供監聽器功能,讓您可以存取 `onMount` 和 `onSubmit` 事件,並將 `onChange` 和 `onBlur` 事件傳播給所有子欄位。 + +`onMount` 和 `onSubmit` 監聽器可存取以下屬性: + +- `formApi` + +`onChange` 和 `onBlur` 監聽器則可存取: + +- `fieldApi` +- `formApi` + +```tsx +const form = useForm({ + listeners: { + onMount: ({ formApi }) => { + // 自訂紀錄服務 + loggingService('mount', formApi.state.values) + }, + + onChange: ({ formApi, fieldApi }) => { + // 自動儲存邏輯 + if (formApi.state.isValid) { + formApi.handleSubmit() + } + + // fieldApi 代表觸發事件的欄位 + console.log(fieldApi.name, fieldApi.state.value) + }, + }, +}) +``` diff --git a/docs/zh-hant/framework/react/guides/react-native.md b/docs/zh-hant/framework/react/guides/react-native.md new file mode 100644 index 000000000..ac519ff4f --- /dev/null +++ b/docs/zh-hant/framework/react/guides/react-native.md @@ -0,0 +1,31 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:36:39.479Z' +id: react-native +title: React Native +--- +## 與 React Native 的搭配使用 + +TanStack Form 採用無頭設計 (headless),應該能夠直接支援 React Native 而無需任何額外設定。 + +以下是一個範例: + +```tsx + + val < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + Age: + + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + +``` diff --git a/docs/zh-hant/framework/react/guides/reactivity.md b/docs/zh-hant/framework/react/guides/reactivity.md new file mode 100644 index 000000000..04db5265e --- /dev/null +++ b/docs/zh-hant/framework/react/guides/reactivity.md @@ -0,0 +1,53 @@ +--- +source-updated-at: '2025-03-20T03:01:05.000Z' +translation-updated-at: '2025-04-25T20:33:36.696Z' +id: reactivity +title: 響應式 +--- +Tanstack Form 在與表單互動時不會觸發重新渲染 (re-renders)。因此,您可能會發現自己試圖使用表單或欄位狀態值卻無法成功。 + +如果您想存取響應式 (reactive) 值,您需要使用以下兩種方法之一來訂閱它們:`useStore` 或 `form.Subscribe` 元件。 + +這些訂閱的用途包括渲染最新的欄位值、根據條件決定渲染內容,或在元件邏輯中使用欄位值。 + +> 若您想「響應」觸發事件,請參閱 [listener](./listeners.md) API。 + +## useStore + +當您需要在元件邏輯中存取表單值時,`useStore` 鉤子 (hook) 是最佳選擇。`useStore` 接受兩個參數:首先是表單儲存庫 (store),其次是一個選擇器 (selector),用於精確訂閱您想關注的表單部分。 + +```tsx +const firstName = useStore(form.store, (state) => state.values.firstName) +const errors = useStore(form.store, (state) => state.errorMap) +``` + +您可以在選擇器中存取表單狀態的任何部分。 + +> 請注意,當訂閱的值變更時,`useStore` 會導致整個元件重新渲染 (re-render)。 + +雖然可以省略選擇器,但請避免這樣做,因為省略它會導致每當表單狀態有任何變更時,都會觸發許多不必要的重新渲染。 + +## form.Subscribe + +當您需要在元件的使用者介面 (UI) 中對某些內容做出反應時,`form.Subscribe` 元件是最適合的選擇。例如,根據表單欄位的值顯示或隱藏 UI 元素。 + +```tsx + state.values.firstName} + children={(firstName) => ( + + {(field) => ( + + )} + + )} +/> +``` + +> `form.Subscribe` 元件不會觸發元件層級的重新渲染。每當訂閱的值變更時,只有 `form.Subscribe` 元件本身會重新渲染。 + +選擇使用 `useStore` 還是 `form.Subscribe` 主要取決於以下情況:如果需要渲染在 UI 中,請選擇 `form.Subscribe` 以獲得其優化優勢;如果需要在邏輯中實現響應性 (reactivity),則應選擇 `useStore`。 diff --git a/docs/zh-hant/framework/react/guides/ssr.md b/docs/zh-hant/framework/react/guides/ssr.md new file mode 100644 index 000000000..d776bade7 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/ssr.md @@ -0,0 +1,493 @@ +--- +source-updated-at: '2025-03-28T18:10:56.000Z' +translation-updated-at: '2025-04-25T20:39:00.310Z' +id: ssr +title: 伺服器渲染 (SSR)/TanStack Start/Next.js +--- +TanStack Form 預設即與 React 相容,支援 `SSR` 且為框架無關 (framework-agnostic)。但根據您選擇的框架,仍需進行特定配置。 + +目前我們支援以下元框架 (meta-frameworks): + +- [TanStack Start](https://tanstack.com/start/) +- [Next.js](https://nextjs.org/) +- [Remix](https://remix.run) + +## 在 TanStack Start 中使用 TanStack Form + +本節重點說明如何將 TanStack Form 整合至 TanStack Start。 + +### TanStack Start 前置準備 + +- 依照 [TanStack Start 快速入門指南](https://tanstack.com/router/latest/docs/framework/react/guide/tanstack-start) 建立新專案 +- 安裝 `@tanstack/react-form` + +### 開始整合 + +首先建立一個 `formOption`,用於在客戶端與伺服器端共享表單結構: + +```typescript +// app/routes/index.tsx,也可提取至其他路徑 +import { formOptions } from '@tanstack/react-form' + +// 可在此傳遞其他表單選項 +export const formOpts = formOptions({ + defaultValues: { + firstName: '', + age: 0, + }, +}) +``` + +接著建立 [Start 伺服器動作 (Server Action)](https://tanstack.com/start/latest/docs/framework/react/server-functions) 來處理伺服器端的表單提交: + +```typescript +// app/routes/index.tsx,也可提取至其他路徑 +import { + createServerValidate, + ServerValidateError, +} from '@tanstack/react-form/start' + +const serverValidate = createServerValidate({ + ...formOpts, + onServerValidate: ({ value }) => { + if (value.age < 12) { + return '伺服器驗證:註冊年齡必須至少 12 歲' + } + }, +}) + +export const handleForm = createServerFn({ + method: 'POST', +}) + .validator((data: unknown) => { + if (!(data instanceof FormData)) { + throw new Error('無效的表單資料') + } + return data + }) + .handler(async (ctx) => { + try { + const validatedData = await serverValidate(ctx.data) + console.log('驗證資料', validatedData) + // 將表單資料存入資料庫 + // await sql` + // INSERT INTO users (name, email, password) + // VALUES (${validatedData.name}, ${validatedData.email}, ${validatedData.password}) + // ` + } catch (e) { + if (e instanceof ServerValidateError) { + // 在此記錄表單錯誤或執行其他邏輯 + return e.response + } + + // 解析表單時發生其他錯誤 + console.error(e) + setResponseStatus(500) + return '發生內部錯誤' + } + + return '表單驗證成功' + }) +``` + +然後建立另一個伺服器動作來從 `serverValidate` 的 `response` 獲取表單資料: + +```typescript +// app/routes/index.tsx,也可提取至其他路徑 +import { getFormData } from '@tanstack/react-form/start' + +export const getFormDataFromServer = createServerFn({ method: 'GET' }).handler( + async () => { + return getFormData() + }, +) +``` + +最後在 loader 中使用 `getFormDataFromServer` 將伺服器狀態傳遞至客戶端,並在客戶端表單元件中使用 `handleForm`: + +```tsx +// app/routes/index.tsx +import { createFileRoute } from '@tanstack/react-router' +import { + mergeForm, + useForm, + useStore, + useTransform, +} from '@tanstack/react-form' + +export const Route = createFileRoute('/')({ + component: Home, + loader: async () => ({ + state: await getFormDataFromServer(), + }), +}) + +function Home() { + const { state } = Route.useLoaderData() + const form = useForm({ + ...formOpts, + transform: useTransform((baseForm) => mergeForm(baseForm, state), [state]), + }) + + const formErrors = useStore(form.store, (formState) => formState.errors) + + return ( +
+ {formErrors.map((error) => ( +

{error}

+ ))} + + + value < 8 ? '客戶端驗證:年齡必須至少 8 歲' : undefined, + }} + > + {(field) => { + return ( +
+ field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors.map((error) => ( +

{error}

+ ))} +
+ ) + }} +
+ [formState.canSubmit, formState.isSubmitting]} + > + {([canSubmit, isSubmitting]) => ( + + )} + +
+ ) +} +``` + +## 在 Next.js App Router 中使用 TanStack Form + +> 閱讀本節前,建議先了解 React 伺服器元件 (Server Components) 和伺服器動作 (Server Actions) 的運作原理。[參考此部落格系列獲取更多資訊](https://playfulprogramming.com/collections/react-beyond-the-render) + +本節重點說明如何將 TanStack Form 整合至 `Next.js`,特別是使用 `App Router` 和 `Server Actions`。 + +### Next.js 前置準備 + +- 依照 [Next.js 文件](https://nextjs.org/docs/getting-started/installation) 建立新專案。設定時請對 `Would you like to use App Router?` 選擇 `yes` 以使用 Next.js 提供的新功能 +- 安裝 `@tanstack/react-form` +- 安裝任選的 [表單驗證器](/form/latest/docs/framework/react/guides/validation#validation-through-schema-libraries) [選用] + +## App Router 整合 + +首先建立一個 `formOption`,用於在客戶端與伺服器端共享表單結構: + +```typescript +// shared-code.ts +// 注意導入路徑與客戶端不同 +import { formOptions } from '@tanstack/react-form/nextjs' + +// 可在此傳遞其他表單選項 +export const formOpts = formOptions({ + defaultValues: { + firstName: '', + age: 0, + }, +}) +``` + +接著建立 [React 伺服器動作](https://playfulprogramming.com/posts/what-are-react-server-components) 來處理伺服器端的表單提交: + +```typescript +// action.ts +'use server' + +// 注意導入路徑與客戶端不同 +import { + ServerValidateError, + createServerValidate, +} from '@tanstack/react-form/nextjs' +import { formOpts } from './shared-code' + +// 建立伺服器動作,將從 `formOpts` 推斷表單類型 +const serverValidate = createServerValidate({ + ...formOpts, + onServerValidate: ({ value }) => { + if (value.age < 12) { + return '伺服器驗證:註冊年齡必須至少 12 歲' + } + }, +}) + +export default async function someAction(prev: unknown, formData: FormData) { + try { + const validatedData = await serverValidate(formData) + console.log('驗證資料', validatedData) + // 將表單資料存入資料庫 + // await sql` + // INSERT INTO users (name, email, password) + // VALUES (${validatedData.name}, ${validatedData.email}, ${validatedData.password}) + // ` + } catch (e) { + if (e instanceof ServerValidateError) { + return e.formState + } + + // 驗證表單時發生其他錯誤 + throw e + } + + // 表單驗證成功! +} +``` + +最後在客戶端表單元件中使用 `someAction`: + +```tsx +// client-component.tsx +'use client' + +import { useActionState } from 'react' +import { initialFormState } from '@tanstack/react-form/nextjs' +// 注意從 `react-form` 而非 `react-form/nextjs` 導入 +import { + mergeForm, + useForm, + useStore, + useTransform, +} from '@tanstack/react-form' +import someAction from './action' +import { formOpts } from './shared-code' + +export const ClientComp = () => { + const [state, action] = useActionState(someAction, initialFormState) + + const form = useForm({ + ...formOpts, + transform: useTransform((baseForm) => mergeForm(baseForm, state!), [state]), + }) + + const formErrors = useStore(form.store, (formState) => formState.errors) + + return ( +
form.handleSubmit()}> + {formErrors.map((error) => ( +

{error}

+ ))} + + + value < 8 ? '客戶端驗證:年齡必須至少 8 歲' : undefined, + }} + > + {(field) => { + return ( +
+ field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors.map((error) => ( +

{error}

+ ))} +
+ ) + }} +
+ [formState.canSubmit, formState.isSubmitting]} + > + {([canSubmit, isSubmitting]) => ( + + )} + +
+ ) +} +``` + +此處我們使用 [React 的 `useActionState` 鉤子](https://playfulprogramming.com/posts/what-is-use-action-state-and-form-status) 和 TanStack Form 的 `useTransform` 鉤子來合併從伺服器動作返回的狀態與表單狀態。 + +> 若在 Next.js 應用中遇到以下錯誤: +> +> ```typescript +> x 您正在導入需要 `useState` 的元件。此 React 鉤子僅能在客戶端元件中運作。解決方法:在檔案(或其父級)加上 `"use client"` 指令 +> ``` +> +> 這是因為您未從 `@tanstack/react-form/nextjs` 導入伺服器端程式碼。請確保根據環境導入正確的模組。 +> +> [這是 Next.js 的限制](https://github.com/phryneas/rehackt)。其他元框架可能不會有相同問題。 + +## 在 Remix 中使用 TanStack Form + +> 閱讀本節前,建議先了解 Remix 動作的運作原理。[參考 Remix 文件獲取更多資訊](https://remix.run/docs/en/main/discussion/data-flow#route-action) + +### Remix 前置準備 + +- 依照 [Remix 文件](https://remix.run/docs/en/main/start/quickstart) 建立新專案 +- 安裝 `@tanstack/react-form` +- 安裝任選的 [表單驗證器](/form/latest/docs/framework/react/guides/validation#validation-through-schema-libraries) [選用] + +## Remix 整合 + +首先建立一個 `formOption`,用於在客戶端與伺服器端共享表單結構: + +```typescript +// routes/_index/route.tsx +import { formOptions } from '@tanstack/react-form/remix' + +// 可在此傳遞其他表單選項 +export const formOpts = formOptions({ + defaultValues: { + firstName: '', + age: 0, + }, +}) +``` + +接著建立 [動作 (action)](https://remix.run/docs/en/main/discussion/data-flow#route-action) 來處理伺服器端的表單提交: + +```tsx +// routes/_index/route.tsx + +import { + ServerValidateError, + createServerValidate, + formOptions, +} from '@tanstack/react-form/remix' + +import type { ActionFunctionArgs } from '@remix-run/node' + +// export const formOpts = formOptions({ + +// 建立伺服器動作,將從 `formOpts` 推斷表單類型 +const serverValidate = createServerValidate({ + ...formOpts, + onServerValidate: ({ value }) => { + if (value.age < 12) { + return '伺服器驗證:註冊年齡必須至少 12 歲' + } + }, +}) + +export async function action({ request }: ActionFunctionArgs) { + const formData = await request.formData() + try { + const validatedData = await serverValidate(formData) + console.log('驗證資料', validatedData) + // 將表單資料存入資料庫 + // await sql` + // INSERT INTO users (name, email, password) + // VALUES (${validatedData.name}, ${validatedData.email}, ${validatedData.password}) + // ` + } catch (e) { + if (e instanceof ServerValidateError) { + return e.formState + } + + // 驗證表單時發生其他錯誤 + throw e + } + + // 表單驗證成功! +} +``` + +最後,提交表單時會呼叫 `action`: + +```tsx +// routes/_index/route.tsx +import { Form, useActionData } from '@remix-run/react' + +import { + mergeForm, + useForm, + useStore, + useTransform, +} from '@tanstack/react-form' +import { + ServerValidateError, + createServerValidate, + formOptions, + initialFormState, +} from '@tanstack/react-form/remix' + +import type { ActionFunctionArgs } from '@remix-run/node' + +// export const formOpts = formOptions({ + +// const serverValidate = createServerValidate({ + +// export async function action({request}: ActionFunctionArgs) { + +export default function Index() { + const actionData = useActionData() + + const form = useForm({ + ...formOpts, + transform: useTransform( + (baseForm) => mergeForm(baseForm, actionData ?? initialFormState), + [actionData], + ), + }) + + const formErrors = useStore(form.store, (formState) => formState.errors) + + return ( +
form.handleSubmit()}> + {formErrors.map((error) => ( +

{error}

+ ))} + + + value < 8 ? '客戶端驗證:年齡必須至少 8 歲' : undefined, + }} + > + {(field) => { + return ( +
+ field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors.map((error) => ( +

{error}

+ ))} +
+ ) + }} +
+ [formState.canSubmit, formState.isSubmitting]} + > + {([canSubmit, isSubmitting]) => ( + + )} + +
+ ) +} +``` + +此處我們使用 [Remix 的 `useActionData` 鉤子](https://remix.run/docs/en/main/hooks/use-action-data) 和 TanStack Form 的 `useTransform` 鉤子來合併從伺服器動作返回的狀態與表單狀態。 diff --git a/docs/zh-hant/framework/react/guides/submission-handling.md b/docs/zh-hant/framework/react/guides/submission-handling.md new file mode 100644 index 000000000..2c034b884 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/submission-handling.md @@ -0,0 +1,41 @@ +--- +source-updated-at: '2025-03-28T15:34:36.000Z' +translation-updated-at: '2025-04-25T20:33:27.381Z' +id: submission-handling +title: 提交處理 +--- +在需要處理多種表單提交類型的情境下,例如一個表單同時包含導向子表單的按鈕與處理標準提交的按鈕,您可以利用 `onSubmitMeta` 屬性與 `handleSubmit` 函式的多載功能來實現。 + +## 基本用法 + +首先必須定義 `form.onSubmitMeta` 屬性的預設狀態: + +```tsx +const form = useForm({ + defaultValues: { + firstName: 'Rick', + }, + // {} 是傳遞給 `onSubmit` 中 `meta` 屬性的預設值 + onSubmitMeta: {} as { lastName: string }, + onSubmit: async ({ value, meta }) => { + // 透過 handleSubmit 傳遞的值進行操作 + console.log(`${value.firstName} - ${meta}`) + }, +}) +``` + +注意:`onSubmitMeta` 的預設狀態為 `never`,若未提供此屬性卻嘗試在 `handleSubmit` 或 `onSubmit` 中存取時,將會引發錯誤。 + +接著在呼叫 `onSubmit` 時,可以像這樣傳遞預先定義的 meta 資料: + +```tsx +
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit({ + lastName: 'Astley', + }) + }} +>
+``` diff --git a/docs/zh-hant/framework/react/guides/ui-libraries.md b/docs/zh-hant/framework/react/guides/ui-libraries.md new file mode 100644 index 000000000..f491f6283 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/ui-libraries.md @@ -0,0 +1,127 @@ +--- +source-updated-at: '2025-03-28T15:34:36.000Z' +translation-updated-at: '2025-04-25T20:33:55.670Z' +id: ui-libraries +title: UI 函式庫 +--- +## 搭配 UI 函式庫使用 TanStack Form + +TanStack Form 是一個無頭 (headless) 函式庫,提供完整的樣式自訂彈性。它能與多種 UI 函式庫相容,包括 `Tailwind`、`Material UI`、`Mantine`,甚至是純 CSS。 + +本指南以 `Material UI` 和 `Mantine` 為重點,但這些概念同樣適用於您選擇的任何 UI 函式庫。 + +### 必要條件 + +在整合 TanStack Form 與 UI 函式庫前,請確保專案中已安裝必要的相依套件: + +- 使用 `Material UI` 時,請遵循其[官方網站](https://mui.com/material-ui/getting-started/)的安裝說明 +- 使用 `Mantine` 時,請參考其[文件](https://mantine.dev/) + +注意:雖然可以混用不同函式庫,但建議保持一致性以維持程式碼簡潔。 + +### Mantine 整合範例 + +以下示範如何將 TanStack Form 與 Mantine 元件整合: + +```tsx +import { TextInput, Checkbox } from '@mantine/core' +import { useForm } from '@tanstack/react-form' + +export default function App() { + const { Field, handleSubmit, state } = useForm({ + defaultValues: { + firstName: '', + lastName: '', + isChecked: false, + }, + onSubmit: async ({ value }) => { + // Handle form submission + console.log(value) + }, + }) + + return ( + <> +
{ + e.preventDefault() + handleSubmit() + }} + > + ( + handleChange(e.target.value)} + onBlur={handleBlur} + placeholder="Enter your name" + /> + )} + /> + ( + handleChange(e.target.checked)} + onBlur={handleBlur} + checked={state.value} + /> + )} + /> + +
+
{JSON.stringify(state.values, null, 2)}
+
+ + ) +} +``` + +- 首先使用 TanStack 的 `useForm` 鉤子並解構所需屬性。此步驟為選用,您也可以直接使用 `const form = useForm()`。TypeScript 的型別推論能確保兩種寫法都有良好的開發體驗。 +- 從 `useForm` 取得的 `Field` 元件接受多種屬性,例如 `validators`。本範例主要聚焦兩個核心屬性:`name` 和 `children`。 + - `name` 屬性用於識別每個 `Field`,例如範例中的 `firstName` + - `children` 屬性採用渲染屬性 (render props) 模式,讓我們能直接整合元件而無需額外抽象層 +- TanStack 的設計大量運用渲染屬性,在 `Field` 元件中提供完整的型別安全。當與 Mantine 元件 (如 `TextInput`) 整合時,我們選擇性地解構 `state.value`、`handleChange` 和 `handleBlur` 等屬性。這種選擇性解構是因為 `TextInput` 與 children 中取得的 `field` 在型別上有些微差異。 +- 遵循這些步驟,您就能無縫整合 Mantine 元件與 TanStack Form +- 此方法同樣適用於其他元件如 `Checkbox`,確保不同 UI 元素間的整合一致性 + +### 搭配 Material UI 使用 + +整合 Material UI 元件的流程類似。以下是使用 Material UI 的 TextField 和 Checkbox 範例: + +```tsx + { + return ( + handleChange(e.target.value)} + onBlur={handleBlur} + placeholder="Enter your last name" + /> + ); + }} + /> + + { + return ( + handleChange(e.target.checked)} + onBlur={handleBlur} + checked={state.value} + /> + ); + }} + /> + +``` + +- 整合方式與 Mantine 相同 +- 主要差異在於 Material UI 元件的特定屬性和樣式選項 diff --git a/docs/zh-hant/framework/react/guides/validation.md b/docs/zh-hant/framework/react/guides/validation.md new file mode 100644 index 000000000..2e83497a6 --- /dev/null +++ b/docs/zh-hant/framework/react/guides/validation.md @@ -0,0 +1,554 @@ +--- +source-updated-at: '2025-04-16T14:15:06.000Z' +translation-updated-at: '2025-04-25T20:34:32.838Z' +id: form-validation +title: 表單驗證 +--- +## 表單與欄位驗證 (Form and Field Validation) + +TanStack Form 的核心功能之一就是驗證機制。TanStack Form 讓驗證功能高度可自訂: + +- 您可以控制驗證的時機(在變更時、輸入時、失去焦點時、提交時...) +- 驗證規則可以在欄位層級或表單層級定義 +- 驗證可以是同步或非同步的(例如 API 呼叫的結果) + +## 驗證何時執行? + +由您決定!`` 元件接受一些回調函式作為 props,例如 `onChange` 或 `onBlur`。這些回調會接收欄位的當前值以及 fieldAPI 物件,讓您可以執行驗證。如果發現驗證錯誤,只需返回錯誤訊息字串,它就會出現在 `field.state.meta.errors` 中。 + +以下是一個範例: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +在上面的範例中,驗證在每次按鍵時執行(`onChange`)。如果我們希望驗證在欄位失去焦點時執行,可以這樣修改程式碼: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +因此,您可以透過實作所需的回調來控制驗證的時機。您甚至可以在不同時間執行不同的驗證: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + onBlur: ({ value }) => (value < 0 ? 'Invalid value' : undefined), + }} +> + {(field) => ( + <> + + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +在上面的範例中,我們在同一欄位的不同時間(每次按鍵和失去焦點時)驗證不同內容。由於 `field.state.meta.errors` 是一個陣列,所有相關錯誤都會在給定時間顯示。您也可以使用 `field.state.meta.errorMap` 根據驗證執行的時間(onChange、onBlur 等)取得錯誤。更多關於顯示錯誤的資訊如下。 + +## 顯示錯誤 + +一旦設定好驗證,您可以將錯誤從陣列映射到 UI 中顯示: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => { + return ( + <> + {/* ... */} + {field.state.meta.errors.length ? ( + {field.state.meta.errors.join(',')} + ) : null} + + ) + }} + +``` + +或者使用 `errorMap` 屬性來存取特定錯誤: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + {/* ... */} + {field.state.meta.errorMap['onChange'] ? ( + {field.state.meta.errorMap['onChange']} + ) : null} + + )} + +``` + +值得一提的是,我們的 `errors` 陣列和 `errorMap` 與驗證器返回的類型匹配。這意味著: + +```tsx + (value < 13 ? { isOldEnough: false } : undefined), + }} +> + {(field) => ( + <> + {/* ... */} + {/* errorMap.onChange 的類型是 `{isOldEnough: false} | undefined` */} + {/* meta.errors 的類型是 `Array<{isOldEnough: false} | undefined>` */} + {!field.state.meta.errorMap['onChange']?.isOldEnough ? ( + The user is not old enough + ) : null} + + )} + +``` + +## 欄位層級與表單層級的驗證 + +如上所示,每個 `` 透過 `onChange`、`onBlur` 等回調接受自己的驗證規則。也可以透過將類似的回調傳遞給 `useForm()` 鉤子來定義表單層級的驗證規則(而不是逐個欄位定義)。 + +範例: + +```tsx +export default function App() { + const form = useForm({ + defaultValues: { + age: 0, + }, + onSubmit: async ({ value }) => { + console.log(value) + }, + validators: { + // 以與欄位相同的方式向表單添加驗證器 + onChange({ value }) { + if (value.age < 13) { + return 'Must be 13 or older to sign' + } + return undefined + }, + }, + }) + + // 訂閱表單的錯誤映射,以便更新時重新渲染 + // 或者,您可以使用 `form.Subscribe` + const formErrorMap = useStore(form.store, (state) => state.errorMap) + + return ( +
+ {/* ... */} + {formErrorMap.onChange ? ( +
+ There was an error on the form: {formErrorMap.onChange} +
+ ) : null} + {/* ... */} +
+ ) +} +``` + +### 從表單驗證器設置欄位層級錯誤 + +您可以從表單的驗證器中設置欄位錯誤。一個常見的用例是在表單的 `onSubmitAsync` 驗證器中呼叫單個 API 端點來驗證所有欄位。 + +```tsx +export default function App() { + const form = useForm({ + defaultValues: { + age: 0, + }, + validators: { + onSubmitAsync: async ({ value }) => { + // 在伺服器上驗證年齡 + const isOlderThan13 = await verifyAgeOnServer(value.age) + if (!isOlderThan13) { + return { + form: 'Invalid data', // `form` 鍵是可選的 + fields: { + age: 'Must be 13 or older to sign', + }, + } + } + + return null + }, + }, + }) + + return ( +
+
{ + e.preventDefault() + e.stopPropagation() + void form.handleSubmit() + }} + > + + {(field) => ( + <> + + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + + [state.errorMap]} + children={([errorMap]) => + errorMap.onSubmit ? ( +
+ There was an error on the form: {errorMap.onSubmit} +
+ ) : null + } + /> + {/*...*/} + +
+ ) +} +``` + +> 值得一提的是,如果您有一個返回錯誤的表單驗證函數,該錯誤可能會被欄位特定的驗證覆蓋。 +> +> 這意味著: +> +> ```jsx +> const form = useForm({ +> defaultValues: { +> age: 0, +> }, +> validators: { +> onChange: ({ value }) => { +> return { +> fields: { +> age: value.age < 12 ? 'Too young!' : undefined, +> }, +> } +> }, +> }, +> }) +> +> // ... +> +> return ( +> name="age" +> validators={{ +> onChange: ({ value }) => (value % 2 === 0 ? 'Must be odd!' : undefined), +> }} +> /> +> ) +> ``` +> +> 即使表單層級驗證返回了 'Too young!' 錯誤,也只會顯示 `'Must be odd!'`。 + +## 非同步函數驗證 + +雖然我們認為大多數驗證會是同步的,但在許多情況下,進行網路呼叫或其他非同步操作來驗證會很有用。 + +為此,我們提供了專用的 `onChangeAsync`、`onBlurAsync` 等方法來進行驗證: + +```tsx + { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value < 13 ? 'You must be 13 to make an account' : undefined + }, + }} +> + {(field) => ( + <> + + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +同步和非同步驗證可以共存。例如,可以在同一欄位上同時定義 `onBlur` 和 `onBlurAsync`: + +```tsx + (value < 13 ? 'You must be at least 13' : undefined), + onBlurAsync: async ({ value }) => { + const currentAge = await fetchCurrentAgeOnProfile() + return value < currentAge ? 'You can only increase the age' : undefined + }, + }} +> + {(field) => ( + <> + + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors ? ( + {field.state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +同步驗證方法(`onBlur`)會先執行,非同步方法(`onBlurAsync`)只有在同步方法(`onBlur`)成功時才會執行。要改變這種行為,請將 `asyncAlways` 選項設為 `true`,這樣無論同步方法的結果如何,非同步方法都會執行。 + +### 內建防抖動 (Debouncing) + +雖然非同步呼叫是在驗證資料庫時的好方法,但在每次按鍵時發送網路請求是對資料庫進行 DDOS 攻擊的好方法。 + +相反,我們提供了一種簡單的方法來防抖動您的 `async` 呼叫,只需添加一個屬性: + +```tsx + { + // ... + }, + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +這將以 500 毫秒的延遲防抖動每個非同步呼叫。您甚至可以針對每個驗證屬性覆蓋此屬性: + +```tsx + { + // ... + }, + onBlurAsync: async ({ value }) => { + // ... + }, + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +> 這將每 1500 毫秒執行一次 `onChangeAsync`,而 `onBlurAsync` 將每 500 毫秒執行一次。 + +## 透過結構描述 (Schema) 函式庫進行驗證 + +雖然函數提供了更多靈活性和自訂驗證的能力,但它們可能有點冗長。為了解決這個問題,有一些函式庫提供了基於結構描述的驗證,使簡寫和類型嚴格的驗證變得更加容易。您還可以為整個表單定義一個結構描述並將其傳遞給表單層級,錯誤將自動傳播到欄位。 + +### 標準結構描述 (Standard Schema) 函式庫 + +TanStack Form 原生支援所有遵循 [Standard Schema 規範](https://github.com/standard-schema/standard-schema) 的函式庫,最著名的包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) +- [Effect/Schema](https://effect.website/docs/schema/standard-schema/) + +_注意:_ 請確保使用結構描述函式庫的最新版本,因為舊版本可能還不支援 Standard Schema。 + +要使用這些函式庫的結構描述,您可以像使用自訂函數一樣將它們傳遞給 `validators` props: + +```tsx +const userSchema = z.object({ + age: z.number().gte(13, 'You must be 13 to make an account'), +}) + +function App() { + const form = useForm({ + defaultValues: { + age: 0, + }, + validators: { + onChange: userSchema, + }, + }) + return ( +
+ { + return <>{/* ... */} + }} + /> +
+ ) +} +``` + +表單和欄位層級的非同步驗證也受到支援: + +```tsx + { + const currentAge = await fetchCurrentAgeOnProfile() + return value >= currentAge + }, + { + message: 'You can only increase the age', + }, + ), + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +如果您需要對 Standard Schema 驗證進行更多控制,可以像這樣將 Standard Schema 與回調函數結合使用: + +```tsx + { + const errors = fieldApi.parseValueWithSchema( + z.number().gte(13, 'You must be 13 to make an account'), + ) + if (errors) return errors + // 繼續進行您的驗證 + }, + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +## 防止提交無效表單 + +`onChange`、`onBlur` 等回調也會在提交表單時執行,如果表單無效,提交將被阻止。 + +表單狀態物件有一個 `canSubmit` 標誌,當任何欄位無效且表單已被觸碰時為 false(`canSubmit` 在表單被觸碰之前為 true,即使某些欄位根據其 `onChange`/`onBlur` props 在「技術上」無效)。 + +您可以透過 `form.Subscribe` 訂閱它,並使用該值來實現例如在表單無效時禁用提交按鈕(實際上,禁用的按鈕不可訪問,請改用 `aria-disabled`)。 + +```tsx +const form = useForm(/* ... */) + +return ( + /* ... */ + + // 動態提交按鈕 + [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + + )} + /> +) +``` diff --git a/docs/zh-hant/framework/react/quick-start.md b/docs/zh-hant/framework/react/quick-start.md new file mode 100644 index 000000000..c7bb8dce0 --- /dev/null +++ b/docs/zh-hant/framework/react/quick-start.md @@ -0,0 +1,137 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:32:32.369Z' +id: quick-start +title: 快速開始 +--- +TanStack Form 與您過去使用的大多數表單函式庫截然不同。它專為大規模生產環境設計,著重於類型安全、效能和組合性,提供無與倫比的開發體驗。 + +因此,我們圍繞函式庫的使用發展出一套[哲學理念](/form/latest/docs/philosophy),重視可擴展性和長期的開發體驗,而非簡短可分享的程式碼片段。 + +以下是一個遵循我們最佳實踐的表單範例,讓您在短暫上手後就能快速開發高複雜度的表單: + +```tsx +import React from 'react' +import ReactDOM from 'react-dom/client' +import { createFormHook, createFormHookContexts } from '@tanstack/react-form' +// 預先綁定表單鉤子事件的表單元件;詳見我們的「表單組合」指南 +import { TextField, NumberField, SubmitButton } from '~our-app/ui-library' +// 我們也支援 Valibot、ArkType 和其他標準的 schema 函式庫 +import { z } from 'zod' + +const { fieldContext, formContext } = createFormHookContexts() + +// 讓我們能將元件綁定到表單,保持類型安全同時減少生產環境的樣板程式碼 +// 定義一次即可在整個應用中生成一致的表單實例 +const { useAppForm } = createFormHook({ + fieldComponents: { + TextField, + NumberField, + }, + formComponents: { + SubmitButton, + }, + fieldContext, + formContext, +}) + +const PeoplePage = () => { + const form = useAppForm({ + defaultValues: { + username: '', + age: 0, + }, + validators: { + // 傳入 schema 或函式進行驗證 + onChange: z.object({ + username: z.string(), + age: z.number().min(13), + }), + }, + onSubmit: ({ value }) => { + // 處理表單資料 + alert(JSON.stringify(value, null, 2)) + }, + }) + + return ( +
{ + e.preventDefault() + form.handleSubmit() + }} + > +

Personal Information

+ {/* 元件綁定到 `form` 和 `field` 以確保極致的類型安全 */} + {/* 使用 `form.AppField` 渲染綁定到單一欄位的元件 */} + } + /> + {/* 若拼寫錯誤,"name" 屬性會拋出 TypeScript 錯誤 */} + } + /> + {/* `form.AppForm` 中的元件可存取表單上下文 */} + + + + + ) +} + +const rootElement = document.getElementById('root')! +ReactDOM.createRoot(rootElement).render() +``` + +雖然我們通常建議使用 `createFormHook` 以長期減少樣板程式碼,但我們也支援使用 `useForm` 和 `form.Field` 來建立一次性元件和其他行為: + +```tsx +import React from 'react' +import ReactDOM from 'react-dom/client' +import { useForm } from '@tanstack/react-form' + +const PeoplePage = () => { + const form = useForm({ + defaultValues: { + username: '', + age: 0, + }, + onSubmit: ({ value }) => { + // 處理表單資料 + alert(JSON.stringify(value, null, 2)) + }, + }) + + return ( + + value > 13 ? undefined : 'Must be 13 or older', + }} + children={(field) => ( + <> + field.handleChange(e.target.valueAsNumber)} + /> + {field.state.meta.errors.length ? ( + {field.state.meta.errors.join(',')} + ) : null} + + )} + /> + ) +} + +const rootElement = document.getElementById('root')! +ReactDOM.createRoot(rootElement).render() +``` + +`useForm` 的所有屬性都可用於 `useAppForm`,而 `form.Field` 的所有屬性也都可用於 `form.AppField`。 diff --git a/docs/zh-hant/framework/react/reference/functions/field.md b/docs/zh-hant/framework/react/reference/functions/field.md new file mode 100644 index 000000000..6a04b9976 --- /dev/null +++ b/docs/zh-hant/framework/react/reference/functions/field.md @@ -0,0 +1,69 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:54:05.677Z' +id: Field +title: 函式 / Field +--- + + +# 函式: Field() + +```ts +function Field(__namedParameters): ReactNode +``` + +定義於: [packages/react-form/src/useField.tsx:428](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L428) + +一個函式元件,接收欄位選項並以子元件形式傳入渲染函式,最終返回一個 React 元件。 + +`Field` 元件內部使用 `useField` 鉤子 (hook) 來管理欄位實例。 + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* `string` + +• **TData** + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TPatentSubmitMeta** + +## 參數 + +### \_\_namedParameters + +`FieldComponentProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TPatentSubmitMeta`\> + +## 返回值 + +`ReactNode` diff --git a/docs/zh-hant/framework/react/reference/functions/usefield.md b/docs/zh-hant/framework/react/reference/functions/usefield.md new file mode 100644 index 000000000..84c9fea63 --- /dev/null +++ b/docs/zh-hant/framework/react/reference/functions/usefield.md @@ -0,0 +1,69 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:54:17.875Z' +id: useField +title: 函式 / useField +--- +# 函式: useField() + +```ts +function useField(opts): FieldApi & ReactFieldApi +``` + +定義於: [packages/react-form/src/useField.tsx:118](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L118) + +用於管理表單欄位的鉤子 (hook)。 + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* `string` + +• **TData** + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TPatentSubmitMeta** + +## 參數 + +### opts + +`UseFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TPatentSubmitMeta`\> + +包含欄位選項的物件。 + +## 回傳值 + +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TPatentSubmitMeta`\> & `ReactFieldApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TPatentSubmitMeta`\> + +指定欄位的 `FieldApi` 實例。 diff --git a/docs/zh-hant/framework/react/reference/functions/useform.md b/docs/zh-hant/framework/react/reference/functions/useform.md new file mode 100644 index 000000000..90e9785eb --- /dev/null +++ b/docs/zh-hant/framework/react/reference/functions/useform.md @@ -0,0 +1,49 @@ +--- +source-updated-at: '2025-02-25T06:59:48.000Z' +translation-updated-at: '2025-04-25T20:53:54.275Z' +id: useForm +title: 函式 / useForm +--- +# 函式: useForm() + +```ts +function useForm(opts?): ReactFormExtendedApi +``` + +定義於: [packages/react-form/src/useForm.tsx:142](https://github.com/TanStack/form/blob/main/packages/react-form/src/useForm.tsx#L142) + +一個自訂的 React Hook,回傳 `FormApi` 類別的擴充實例。 + +此 API 封裝了所有與表單相關的必要功能。它讓您可以管理表單狀態、處理提交以及與表單欄位互動。 + +## 型別參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TSubmitMeta** + +## 參數 + +### opts? + +`FormOptions`\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +## 回傳值 + +[`ReactFormExtendedApi`](../type-aliases/reactformextendedapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> diff --git a/docs/zh-hant/framework/react/reference/functions/usetransform.md b/docs/zh-hant/framework/react/reference/functions/usetransform.md new file mode 100644 index 000000000..9d1ccd523 --- /dev/null +++ b/docs/zh-hant/framework/react/reference/functions/usetransform.md @@ -0,0 +1,27 @@ +--- +source-updated-at: '2025-03-07T11:44:33.000Z' +translation-updated-at: '2025-04-25T20:53:36.108Z' +id: useTransform +title: 函式 / useTransform +--- +# 函式: useTransform() + +```ts +function useTransform(fn, deps): FormTransform +``` + +定義於: [packages/react-form/src/useTransform.ts:9](https://github.com/TanStack/form/blob/main/packages/react-form/src/useTransform.ts#L9) + +## 參數 + +### fn + +(`formBase`) => `AnyFormApi` + +### deps + +`unknown`[] + +## 回傳值 + +`FormTransform`\<`any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\> diff --git a/docs/zh-hant/framework/react/reference/index.md b/docs/zh-hant/framework/react/reference/index.md new file mode 100644 index 000000000..d64fd0f67 --- /dev/null +++ b/docs/zh-hant/framework/react/reference/index.md @@ -0,0 +1,30 @@ +--- +source-updated-at: '2025-03-06T21:32:39.000Z' +translation-updated-at: '2025-04-25T20:53:38.328Z' +id: '@tanstack/react-form' +title: React 參考 +--- + + +# @tanstack/react-form + +## 介面 (Interfaces) + +- [ReactFormApi](interfaces/reactformapi.md) +- [WithFormProps](interfaces/withformprops.md) + +## 類型別名 (Type Aliases) + +- [FieldComponent](type-aliases/fieldcomponent.md) +- [ReactFormExtendedApi](type-aliases/reactformextendedapi.md) +- [UseField](type-aliases/usefield.md) + +## 函式 (Functions) + +- [createFormHook](functions/createformhook.md) +- [createFormHookContexts](functions/createformhookcontexts.md) +- [Field](functions/field.md) +- [useField](functions/usefield.md) +- [useForm](functions/useform.md) +- [useStore](functions/usestore.md) +- [useTransform](functions/usetransform.md) diff --git a/docs/zh-hant/framework/react/reference/type-aliases/fieldcomponent.md b/docs/zh-hant/framework/react/reference/type-aliases/fieldcomponent.md new file mode 100644 index 000000000..5a1cbf67b --- /dev/null +++ b/docs/zh-hant/framework/react/reference/type-aliases/fieldcomponent.md @@ -0,0 +1,77 @@ +--- +source-updated-at: '2025-04-11T15:48:08.000Z' +translation-updated-at: '2025-04-25T20:54:09.782Z' +id: FieldComponent +title: 類型 / FieldComponent +--- + + +# 類型別名:FieldComponent()\ + +```ts +type FieldComponent = ({ + children, + ...fieldOptions +}) => ReactNode; +``` + +定義於:[packages/react-form/src/useField.tsx:363](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L363) + +一個表示特定表單資料類型的欄位元件類型別名。 + +## 類型參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TPatentSubmitMeta** + +• **ExtendedApi** = \{\} + +## 類型參數 + +• **TName** *繼承自* `DeepKeys`\<`TParentData`\> + +• **TData** *繼承自* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 參數 + +### \{ + children, + ...fieldOptions +\} + +`FieldComponentBoundProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TPatentSubmitMeta`, `ExtendedApi`\> + +## 返回值 + +`ReactNode` diff --git a/docs/zh-hant/framework/react/reference/type-aliases/usefield.md b/docs/zh-hant/framework/react/reference/type-aliases/usefield.md new file mode 100644 index 000000000..f2c4d7d72 --- /dev/null +++ b/docs/zh-hant/framework/react/reference/type-aliases/usefield.md @@ -0,0 +1,69 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:54:14.575Z' +id: UseField +title: 類型 / UseField +--- +# 類型別名:UseField()\ + +```ts +type UseField = (opts) => FieldApi; +``` + +定義於:[packages/react-form/src/useField.tsx:50](https://github.com/TanStack/form/blob/main/packages/react-form/src/useField.tsx#L50) + +一個表示用於在表單中使用欄位的鉤子 (hook) 類型,該表單具有指定的表單資料類型。 + +這是一個函式,接受一個可選物件(包含 `name` 屬性和欄位選項),並返回指定欄位的 `FieldApi` 實例。 + +## 類型參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TPatentSubmitMeta** + +## 類型參數 + +• **TName** *繼承自* `DeepKeys`\<`TParentData`\> + +• **TData** *繼承自* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 參數 + +### opts + +`UseFieldOptionsBound`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> + +## 返回值 + +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TPatentSubmitMeta`\> diff --git a/docs/zh-hant/framework/solid/guides/arrays.md b/docs/zh-hant/framework/solid/guides/arrays.md new file mode 100644 index 000000000..3cfc84582 --- /dev/null +++ b/docs/zh-hant/framework/solid/guides/arrays.md @@ -0,0 +1,125 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:47:44.864Z' +id: arrays +title: 陣列 +--- +TanStack Form 支援將陣列 (array) 作為表單值,包含陣列中的子物件值。 + +## 基本用法 + +要使用陣列,您可以對陣列值使用 `field.state.value`,並搭配 [`solid-js` 的 `Index`](https://www.solidjs.com/tutorial/flow_index): + +```jsx +function App() { + const form = createForm(() => ({ + defaultValues: { + people: [], + }, + })) + + return ( + + {(field) => ( + 0}> + {/* 請勿將此處改為 `For`,否則將無法如預期運作 */} + + { + (_, i) => null // ... + } + + + )} + + ) +} +``` + +> 您必須使用 `solid-js` 的 `Index` 而非 `For`,因為 `For` 會在陣列變更時導致內部元件重新渲染。 +> +> 這會造成欄位值遺失,進而刪除子欄位的值。 + +當您在 `field` 上執行 `pushValue` 時,將會生成映射後的 JSX: + +```jsx + +``` + +最後,您可以像這樣使用子欄位: + +```jsx + + {(subField) => ( + { + subField().handleChange(e.currentTarget.value) + }} + /> + )} + +``` + +## 完整範例 + +```jsx +function App() { + const form = createForm(() => ({ + defaultValues: { + people: [], + }, + onSubmit: ({ value }) => alert(JSON.stringify(value)), + })) + + return ( +
+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > + + {(field) => ( +
+ 0}> + {/* 請勿將此處改為 For,否則測試將失敗 */} + + {(_, i) => ( + + {(subField) => ( +
+ +
+ )} +
+ )} +
+
+ + +
+ )} +
+ +
+
+ ) +} +``` diff --git a/docs/zh-hant/framework/solid/guides/async-initial-values.md b/docs/zh-hant/framework/solid/guides/async-initial-values.md new file mode 100644 index 000000000..c6b41c3ed --- /dev/null +++ b/docs/zh-hant/framework/solid/guides/async-initial-values.md @@ -0,0 +1,49 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:47:32.217Z' +id: async-initial-values +title: 非同步初始值 +--- +假設您想從 API 取得一些資料,並將其作為表單的初始值。 + +雖然這個問題表面上看起來簡單,但背後可能隱藏著您尚未考慮到的複雜性。 + +舉例來說,您可能希望在資料載入時顯示載入動畫,或是優雅地處理錯誤情況。同樣地,您也可能會想尋找快取資料的方法,避免每次渲染表單時都要重新取得資料。 + +雖然我們可以從頭實作這些功能,但最終結果可能會與我們維護的另一個專案 [TanStack Query](https://tanstack.com/query) 非常相似。 + +因此,本指南將展示如何結合使用 TanStack Form 與 TanStack Query 來達成所需行為。 + +## 基本用法 + +```tsx +import { createForm } from '@tanstack/solid-form' +import { createQuery } from '@tanstack/solid-query' + +export default function App() { + const { data, isLoading } = createQuery(() => ({ + queryKey: ['data'], + queryFn: async () => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return { firstName: 'FirstName', lastName: 'LastName' } + }, + })) + + const form = createForm(() => ({ + defaultValues: { + firstName: data?.firstName ?? '', + lastName: data?.lastName ?? '', + }, + onSubmit: async ({ value }) => { + // Do something with form data + console.log(value) + }, + })) + + if (isLoading) return

Loading..

+ + return null +} +``` + +這段程式碼會在資料載入完成前顯示載入提示,待資料取得後,便會以取得的資料作為初始值來渲染表單。 diff --git a/docs/zh-hant/framework/solid/guides/basic-concepts.md b/docs/zh-hant/framework/solid/guides/basic-concepts.md new file mode 100644 index 000000000..25b8964de --- /dev/null +++ b/docs/zh-hant/framework/solid/guides/basic-concepts.md @@ -0,0 +1,296 @@ +--- +source-updated-at: '2025-03-14T21:54:05.000Z' +translation-updated-at: '2025-04-25T20:48:36.269Z' +id: basic-concepts +title: 基本概念 +--- +本頁介紹 `@tanstack/solid-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更好地理解並運用此函式庫。 + +## 表單選項 (Form Options) + +您可以使用 `formOptions` 函式建立表單選項,以便在多個表單之間共享配置。 + +範例: + +```tsx +const formOpts = formOptions({ + defaultValues: { + firstName: '', + lastName: '', + hobbies: [], + } as Person, +}) +``` + +## 表單實例 (Form Instance) + +表單實例是一個代表單一表單的物件,提供操作表單的方法與屬性。您可以使用表單選項提供的 `createForm` 鉤子來建立表單實例。該鉤子接受包含 `onSubmit` 函式的物件,此函式會在表單提交時被呼叫。 + +```tsx +const form = createForm(() => ({ + ...formOpts, + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, +})) +``` + +您也可以不使用 `formOptions`,直接透過獨立的 `createForm` API 建立表單實例: + +```tsx +const form = createForm(() => ({ + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, + defaultValues: { + firstName: '', + lastName: '', + hobbies: [], + }, +})) +``` + +## 欄位 (Field) + +欄位代表單一表單輸入元素,例如文字輸入框或核取方塊。欄位是透過表單實例提供的 `form.Field` 元件建立的。該元件接受一個名稱屬性 (name prop),應與表單預設值中的鍵名匹配。同時也接受子元件屬性 (children prop),這是一個以欄位物件為參數的渲染函式。 + +範例: + +```tsx + ( + field().handleChange(e.target.value)} + /> + )} +/> +``` + +## 欄位狀態 (Field State) + +每個欄位都有自身的狀態,包含當前值、驗證狀態、錯誤訊息和其他元資料。您可以透過 `field().state` 屬性存取欄位狀態。 + +範例: + +```tsx +const { + value, + meta: { errors, isValidating }, +} = field().state +``` + +有三種欄位狀態對了解使用者互動特別有用:當使用者點擊/切換到欄位時會標記為「已觸碰 _(touched)_」;在值被改變前保持「原始 _(pristine)_」狀態;值改變後則標記為「已修改 _(dirty)_」。您可以透過以下標誌檢查這些狀態: + +```tsx +const { isTouched, isPristine, isDirty } = field().state.meta +``` + +![欄位狀態](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/field-states.png) + +## 欄位 API (Field API) + +欄位 API 是建立欄位時傳遞給渲染函式的物件,提供操作欄位狀態的方法。 + +範例: + +```tsx + field().handleChange(e.target.value)} +/> +``` + +## 驗證 (Validation) + +`@tanstack/solid-form` 原生支援同步與非同步驗證。驗證函式可以透過 `validators` 屬性傳遞給 `form.Field` 元件。 + +範例: + +```tsx + + !value + ? '必須填寫名字' + : value.length < 3 + ? '名字至少需要 3 個字元' + : undefined, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value.includes('error') && '名字中不能包含 "error"' + }, + }} + children={(field) => ( + <> + field().handleChange(e.target.value)} + /> +

{field().state.meta.errors[0]}

+ + )} +/> +``` + +## 使用標準結構描述函式庫驗證 (Validation with Standard Schema Libraries) + +除了手動驗證選項外,我們也支援 [標準結構描述 (Standard Schema)](https://github.com/standard-schema/standard-schema) 規範。 + +您可以使用任何實現此規範的函式庫定義結構描述,並將其傳遞給表單或欄位驗證器。 + +支援的函式庫包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +```tsx +import { z } from 'zod' + +// ... +; { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return !value.includes('error') + }, + { + message: '名字中不能包含 "error"', + }, + ), + }} + children={(field) => ( + <> + field().handleChange(e.target.value)} + /> +

{field().state.meta.errors[0]}

+ + )} +/> +``` + +## 響應式 (Reactivity) + +`@tanstack/solid-form` 提供多種訂閱表單與欄位狀態變更的方式,最值得注意的是 `form.useStore` 鉤子與 `form.Subscribe` 元件。這些方法讓您可以透過只在必要時更新元件來優化表單的渲染效能。 + +範例: + +```tsx +const firstName = form.useStore((state) => state.values.firstName) +//... + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + children={(state) => ( + + )} +/> +``` + +## 陣列欄位 (Array Fields) + +陣列欄位讓您能管理表單中的值列表,例如興趣愛好清單。您可以透過 `form.Field` 元件並設定 `mode="array"` 屬性來建立陣列欄位。 + +操作陣列欄位時,可以使用欄位的 `pushValue`、`removeValue`、`swapValues` 和 `moveValue` 方法來新增、刪除和交換陣列中的值。 + +範例: + +```tsx + ( +
+ 興趣愛好 +
+ 0} + fallback={'沒有找到興趣愛好。'} + > + + {(_, i) => ( +
+ ( +
+ + field().handleChange(e.target.value)} + /> + +
+ )} + /> + { + return ( +
+ + field().handleChange(e.target.value)} + /> +
+ ) + }} + /> +
+ )} +
+
+
+ +
+ )} +/> +``` + +以上是 `@tanstack/solid-form` 函式庫中使用的基本概念與術語。理解這些概念將幫助您更有效率地運用此函式庫,輕鬆建立複雜的表單。 diff --git a/docs/zh-hant/framework/solid/guides/linked-fields.md b/docs/zh-hant/framework/solid/guides/linked-fields.md new file mode 100644 index 000000000..31921a34b --- /dev/null +++ b/docs/zh-hant/framework/solid/guides/linked-fields.md @@ -0,0 +1,78 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:47:37.261Z' +id: linked-fields +title: 關聯欄位 +--- +你可能會遇到需要將兩個表單欄位連結在一起的情況:當其中一個欄位需要根據另一個欄位的值變更進行驗證時。 +一個常見的使用情境是當你同時有 `password` 和 `confirm_password` 欄位時, +你會希望當 `password` 的值不匹配時,`confirm_password` 能顯示錯誤; +無論是哪個欄位觸發了值變更。 + +想像以下使用者流程: + +- 使用者更新確認密碼欄位。 +- 使用者更新非確認密碼欄位。 + +在這個例子中,表單仍會顯示錯誤, +因為「確認密碼」欄位的驗證尚未重新執行以標記為已接受。 + +為了解決這個問題,我們需要確保當密碼欄位更新時,「確認密碼」的驗證會重新執行。 +要做到這一點,你可以在 `confirm_password` 欄位中加入 `onChangeListenTo` 屬性。 + +```tsx +export default function App() { + const form = createForm(() => ({ + defaultValues: { + password: '', + confirm_password: '', + }, + // ... + })) + + return ( +
+ + {(field) => ( + + )} + + { + if (value !== fieldApi.form.getFieldValue('password')) { + return 'Passwords do not match' + } + return undefined + }, + }} + > + {(field) => ( +
+ + + {(err) =>
{err()}
} +
+
+ )} +
+
+ ) +} +``` + +同樣地,這也適用於 `onBlurListenTo` 屬性,該屬性會在欄位失去焦點時重新執行驗證。 diff --git a/docs/zh-hant/framework/solid/guides/validation.md b/docs/zh-hant/framework/solid/guides/validation.md new file mode 100644 index 000000000..49e369588 --- /dev/null +++ b/docs/zh-hant/framework/solid/guides/validation.md @@ -0,0 +1,447 @@ +--- +source-updated-at: '2025-04-16T14:15:06.000Z' +translation-updated-at: '2025-04-25T20:49:26.219Z' +id: form-validation +title: 表單驗證 +--- +# 表單與欄位驗證 (Form and Field Validation) + +TanStack Form 的核心功能之一就是驗證機制。TanStack Form 讓驗證功能高度可自訂: + +- 您可以控制驗證的時機 (onChange、onInput、onBlur、onSubmit...) +- 驗證規則可以在欄位層級或表單層級定義 +- 驗證可以是同步或非同步的 (例如 API 呼叫的結果) + +## 驗證何時執行? + +由您決定!`` 元件接受一些回調函式作為 props,例如 `onChange` 或 `onBlur`。這些回調函式會接收欄位的當前值以及 fieldAPI 物件,讓您可以執行驗證。如果發現驗證錯誤,只需返回錯誤訊息字串,它就會出現在 `field().state.meta.errors` 中。 + +以下是一個範例: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + + field().handleChange(e.target.valueAsNumber)} + /> + {field().state.meta.errors ? ( + {field().state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +在上面的範例中,驗證在每次鍵盤輸入時執行 (`onChange`)。如果我們希望驗證在欄位失去焦點時執行,可以這樣修改程式碼: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + + field().handleChange(e.target.valueAsNumber)} + /> + {field().state.meta.errors ? ( + {field().state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +因此,您可以透過實作所需的回調函式來控制驗證的時機。您甚至可以在不同時間執行不同的驗證: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + onBlur: ({ value }) => (value < 0 ? 'Invalid value' : undefined), + }} +> + {(field) => ( + <> + + field().handleChange(e.target.valueAsNumber)} + /> + {field().state.meta.errors ? ( + {field().state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +在上面的範例中,我們對同一欄位在不同時間 (每次鍵盤輸入和欄位失去焦點時) 進行不同的驗證。由於 `field().state.meta.errors` 是一個陣列,所有在特定時間相關的錯誤都會顯示。您也可以使用 `field().state.meta.errorMap` 根據驗證執行的時機 (onChange、onBlur 等) 取得錯誤。更多關於顯示錯誤的資訊如下。 + +## 顯示錯誤 + +設定好驗證後,您可以將錯誤從陣列映射到 UI 中顯示: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => { + return ( + <> + {/* ... */} + {field().state.meta.errors.length ? ( + {field().state.meta.errors.join(',')} + ) : null} + + ) + }} + +``` + +或者使用 `errorMap` 屬性來存取特定的錯誤: + +```tsx + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {(field) => ( + <> + {/* ... */} + {field().state.meta.errorMap['onChange'] ? ( + {field().state.meta.errorMap['onChange']} + ) : null} + + )} + +``` + +值得一提的是,我們的 `errors` 陣列和 `errorMap` 與驗證器返回的類型相匹配。這意味著: + +```tsx + (value < 13 ? { isOldEnough: false } : undefined), + }} +> + {(field) => ( + <> + {/* ... */} + {/* errorMap.onChange 類型為 `{isOldEnough: false} | undefined` */} + {/* meta.errors 類型為 `Array<{isOldEnough: false} | undefined>` */} + {!field().state.meta.errorMap['onChange']?.isOldEnough ? ( + The user is not old enough + ) : null} + + )} + +``` + +## 欄位層級與表單層級的驗證 + +如上所示,每個 `` 透過 `onChange`、`onBlur` 等回調函式接受自己的驗證規則。也可以透過將類似的回調函式傳遞給 `createForm()` hook 來在表單層級定義驗證規則 (而不是逐個欄位定義)。 + +範例: + +```tsx +export default function App() { + const form = createForm(() => ({ + defaultValues: { + age: 0, + }, + onSubmit: async ({ value }) => { + console.log(value) + }, + validators: { + // 以與欄位相同的方式向表單添加驗證器 + onChange({ value }) { + if (value.age < 13) { + return 'Must be 13 or older to sign' + } + return undefined + }, + }, + })) + + // 訂閱表單的 errorMap,以便更新時重新渲染 + // 或者您可以使用 `form.Subscribe` + const formErrorMap = form.useStore((state) => state.errorMap) + + return ( +
+ {/* ... */} + {formErrorMap().onChange ? ( +
+ There was an error on the form: {formErrorMap().onChange} +
+ ) : null} + {/* ... */} +
+ ) +} +``` + +## 非同步函數驗證 + +雖然我們預期大多數驗證會是同步的,但在許多情況下,網路呼叫或其他非同步操作對於驗證會很有用。 + +為此,我們提供了專用的 `onChangeAsync`、`onBlurAsync` 等方法來進行驗證: + +```tsx + { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value < 13 ? 'You must be 13 to make an account' : undefined + }, + }} +> + {(field) => ( + <> + + field().handleChange(e.target.valueAsNumber)} + /> + {field().state.meta.errors ? ( + {field().state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +同步和非同步驗證可以共存。例如,可以在同一欄位上定義 `onBlur` 和 `onBlurAsync`: + +```tsx + (value < 13 ? 'You must be at least 13' : undefined), + onBlurAsync: async ({ value }) => { + const currentAge = await fetchCurrentAgeOnProfile() + return value < currentAge ? 'You can only increase the age' : undefined + }, + }} +> + {(field) => ( + <> + + field().handleChange(e.target.valueAsNumber)} + /> + {field().state.meta.errors ? ( + {field().state.meta.errors.join(', ')} + ) : null} + + )} + +``` + +同步驗證方法 (`onBlur`) 會先執行,非同步方法 (`onBlurAsync`) 只有在同步方法 (`onBlur`) 成功時才會執行。要改變此行為,請將 `asyncAlways` 選項設為 `true`,這樣非同步方法無論同步方法的結果如何都會執行。 + +### 內建防抖動 (Debouncing) + +雖然非同步呼叫是對資料庫進行驗證的好方法,但在每次鍵盤輸入時執行網路請求是對資料庫進行 DDOS 攻擊的好方法。 + +相反地,我們提供了一個簡單的方法來防抖動您的 `async` 呼叫,只需添加一個屬性: + +```tsx + { + // ... + }, + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +這將以 500 毫秒的延遲防抖動每個非同步呼叫。您甚至可以針對每個驗證屬性覆寫此屬性: + +```tsx + { + // ... + }, + onBlurAsync: async ({ value }) => { + // ... + }, + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +> 這將每 1500 毫秒執行一次 `onChangeAsync`,而 `onBlurAsync` 將每 500 毫秒執行一次。 + +## 透過結構描述 (Schema) 函式庫進行驗證 + +雖然函數提供了更多靈活性和自訂驗證的能力,但它們可能有點冗長。為了解決這個問題,有一些函式庫提供了基於結構描述的驗證,使簡寫和類型嚴格的驗證變得更加容易。您還可以為整個表單定義一個結構描述並將其傳遞到表單層級,錯誤將自動傳播到欄位。 + +### 標準結構描述 (Standard Schema) 函式庫 + +TanStack Form 原生支援所有遵循 [Standard Schema 規範](https://github.com/standard-schema/standard-schema) 的函式庫,最著名的包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +_注意:_ 請確保使用結構描述函式庫的最新版本,因為舊版本可能尚未支援 Standard Schema。 + +要使用這些函式庫的結構描述,您可以像使用自訂函數一樣將它們傳遞給 `validators` props: + +```tsx +import { z } from 'zod' + +// ... + +const form = createForm(() => ({ + // ... +})) + +; { + return <>{/* ... */} + }} +/> +``` + +表單和欄位層級的非同步驗證也受支援: + +```tsx + { + const currentAge = await fetchCurrentAgeOnProfile() + return value >= currentAge + }, + { + message: 'You can only increase the age', + }, + ), + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +如果您需要對 Standard Schema 驗證進行更多控制,可以像這樣將 Standard Schema 與回調函式結合使用: + +```tsx + { + const errors = fieldApi.parseValueWithSchema( + z.number().gte(13, 'You must be 13 to make an account'), + ) + + if (errors) return errors + + // 繼續您的驗證 + }, + }} + children={(field) => { + return <>{/* ... */} + }} +/> +``` + +## 防止提交無效表單 + +`onChange`、`onBlur` 等回調函式也會在表單提交時執行,如果表單無效,提交會被阻止。 + +表單狀態物件有一個 `canSubmit` 標誌,當任何欄位無效且表單已被觸碰時,該標誌為 false (`canSubmit` 在表單被觸碰之前為 true,即使某些欄位根據其 `onChange`/`onBlur` props 在「技術上」無效)。 + +您可以透過 `form.Subscribe` 訂閱它,並使用該值來,例如,在表單無效時禁用提交按鈕 (實際上,禁用的按鈕不可訪問,請改用 `aria-disabled`)。 + +```tsx +const form = createForm(() => ({ + /* ... */ +})) + +return ( + /* ... */ + + // 動態提交按鈕 + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + children={(state) => ( + + )} + /> +) +``` diff --git a/docs/zh-hant/framework/solid/quick-start.md b/docs/zh-hant/framework/solid/quick-start.md new file mode 100644 index 000000000..795faea95 --- /dev/null +++ b/docs/zh-hant/framework/solid/quick-start.md @@ -0,0 +1,55 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:31:19.846Z' +id: quick-start +title: 快速開始 +--- +## 快速開始 + +使用 TanStack Form 最基本的入門步驟是建立一個表單並添加欄位。請注意,此範例尚未包含任何驗證或錯誤處理功能。 + +```tsx +import { createForm } from '@tanstack/solid-form' + +function App() { + const form = createForm(() => ({ + defaultValues: { + fullName: '', + }, + onSubmit: async ({ value }) => { + // 對表單資料進行處理 + console.log(value) + }, + })) + + return ( +
+

簡單表單範例

+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > +
+ ( + field().handleChange(e.target.value)} + /> + )} + /> +
+ +
+
+ ) +} +``` + +從這裡開始,您就可以準備探索 TanStack Form 的所有其他功能了! diff --git a/docs/zh-hant/framework/solid/reference/functions/createfield.md b/docs/zh-hant/framework/solid/reference/functions/createfield.md new file mode 100644 index 000000000..9a35a6b92 --- /dev/null +++ b/docs/zh-hant/framework/solid/reference/functions/createfield.md @@ -0,0 +1,67 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:54:58.726Z' +id: createField +title: 函式 / createField +--- +# 函式: createField() + +```ts +function createField(opts): () => FieldApi & SolidFieldApi +``` + +定義於: [packages/solid-form/src/createField.tsx:223](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L223) + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* `string` + +• **TData** + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 參數 + +### opts + +() => `CreateFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> + +## 回傳值 + +`Function` + +### 回傳 + +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> & `SolidFieldApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> diff --git a/docs/zh-hant/framework/solid/reference/functions/createform.md b/docs/zh-hant/framework/solid/reference/functions/createform.md new file mode 100644 index 000000000..612577e4c --- /dev/null +++ b/docs/zh-hant/framework/solid/reference/functions/createform.md @@ -0,0 +1,45 @@ +--- +source-updated-at: '2025-03-01T06:06:46.000Z' +translation-updated-at: '2025-04-25T20:54:38.831Z' +id: createForm +title: 函式 / createForm +--- +# 函式: createForm() + +```ts +function createForm(opts?): FormApi & SolidFormApi +``` + +定義於: [packages/solid-form/src/createForm.tsx:115](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createForm.tsx#L115) + +## 型別參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TSubmitMeta** + +## 參數 + +### opts? + +() => `FormOptions`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> + +## 回傳值 + +`FormApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> & [`SolidFormApi`](../interfaces/solidformapi.md)\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> diff --git a/docs/zh-hant/framework/solid/reference/functions/field.md b/docs/zh-hant/framework/solid/reference/functions/field.md new file mode 100644 index 000000000..d9f09023d --- /dev/null +++ b/docs/zh-hant/framework/solid/reference/functions/field.md @@ -0,0 +1,65 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:54:54.300Z' +id: Field +title: 函式 / Field +--- + + +# 函式: Field() + +```ts +function Field(props): Element +``` + +定義於: [packages/solid-form/src/createField.tsx:524](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L524) + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* `string` + +• **TData** + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 參數 + +### props + +`FieldComponentProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> + +## 回傳值 + +`Element` diff --git a/docs/zh-hant/framework/solid/reference/index.md b/docs/zh-hant/framework/solid/reference/index.md new file mode 100644 index 000000000..2c470a3cc --- /dev/null +++ b/docs/zh-hant/framework/solid/reference/index.md @@ -0,0 +1,25 @@ +--- +source-updated-at: '2025-02-22T01:19:17.000Z' +translation-updated-at: '2025-04-25T20:54:15.964Z' +id: '@tanstack/solid-form' +title: Solid 參考 +--- + + +# @tanstack/solid-form + +## 介面 (Interfaces) + +- [SolidFormApi](interfaces/solidformapi.md) + +## 類型別名 (Type Aliases) + +- [CreateField](type-aliases/createfield.md) +- [FieldComponent](type-aliases/fieldcomponent.md) + +## 函式 (Functions) + +- [createField](functions/createfield.md) +- [createForm](functions/createform.md) +- [Field](functions/field.md) +- [useStore](functions/usestore.md) diff --git a/docs/zh-hant/framework/solid/reference/type-aliases/createfield.md b/docs/zh-hant/framework/solid/reference/type-aliases/createfield.md new file mode 100644 index 000000000..fc162d10b --- /dev/null +++ b/docs/zh-hant/framework/solid/reference/type-aliases/createfield.md @@ -0,0 +1,71 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:55:11.667Z' +id: CreateField +title: 類型 / CreateField +--- + + +# 類型別名:CreateField()\ + +```ts +type CreateField = (opts) => () => FieldApi & SolidFieldApi; +``` + +定義於:[packages/solid-form/src/createField.tsx:49](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L49) + +## 類型參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 類型參數 + +• **TName** *繼承自* `DeepKeys`\<`TParentData`\> + +• **TData** *繼承自* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 參數 + +### opts + +() => `object` & `CreateFieldOptionsBound`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> + +## 回傳值 + +`Function` + +### 回傳 + +`FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> & `SolidFieldApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> diff --git a/docs/zh-hant/framework/solid/reference/type-aliases/fieldcomponent.md b/docs/zh-hant/framework/solid/reference/type-aliases/fieldcomponent.md new file mode 100644 index 000000000..dd16568cd --- /dev/null +++ b/docs/zh-hant/framework/solid/reference/type-aliases/fieldcomponent.md @@ -0,0 +1,73 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:54:58.608Z' +id: FieldComponent +title: 類型 / FieldComponent +--- + + +# 類型別名:FieldComponent()\ + +```ts +type FieldComponent = ({ + children, + ...fieldOptions +}) => JSXElement; +``` + +定義於:[packages/solid-form/src/createField.tsx:400](https://github.com/TanStack/form/blob/main/packages/solid-form/src/createField.tsx#L400) + +## 類型參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 類型參數 + +• **TName** *繼承自* `DeepKeys`\<`TParentData`\> + +• **TData** *繼承自* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 參數 + +### \{ + children, + ...fieldOptions +\} + +`FieldComponentBoundProps`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> + +## 返回值 + +`JSXElement` diff --git a/docs/zh-hant/framework/svelte/guides/arrays.md b/docs/zh-hant/framework/svelte/guides/arrays.md new file mode 100644 index 000000000..1f9e5eacc --- /dev/null +++ b/docs/zh-hant/framework/svelte/guides/arrays.md @@ -0,0 +1,112 @@ +--- +source-updated-at: '2025-04-24T18:50:42.000Z' +translation-updated-at: '2025-04-25T20:49:22.829Z' +id: arrays +title: 陣列 +--- +TanStack Form 支援將陣列 (array) 作為表單值使用,包含陣列中的子物件值。 + +## 基本用法 + +要使用陣列,你可以對陣列值使用 `field.state.value` 並搭配 [`each blocks`](https://svelte.dev/docs/svelte/each): + +```svelte + + + + {#snippet children(field)} + {#each field.state.value as person, i} + + {/each} + {/snippet} + +``` + +這會在每次對 `field` 執行 `pushValue` 時重新生成列表: + +```svelte + +``` + +最後,你可以像這樣使用子欄位 (subfield): + +```svelte + + {#snippet children(subField)} + { + subField.handleChange(e.currentTarget.value) + }} + /> + {/snippet} + +``` + +## 完整範例 + +```svelte + + +
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} +> + + {#snippet children(field)} +
+ {#each field.state.value as person, i} + + {#snippet children(subField)} +
+ +
+ {/snippet} +
+ {/each} + + +
+ {/snippet} +
+ + +
+``` diff --git a/docs/zh-hant/framework/svelte/guides/async-initial-values.md b/docs/zh-hant/framework/svelte/guides/async-initial-values.md new file mode 100644 index 000000000..e5eeed9c2 --- /dev/null +++ b/docs/zh-hant/framework/svelte/guides/async-initial-values.md @@ -0,0 +1,51 @@ +--- +source-updated-at: '2025-04-24T18:50:42.000Z' +translation-updated-at: '2025-04-25T20:47:47.031Z' +id: async-initial-values +title: 非同步初始值 +--- +假設您想從 API 取得一些資料,並將其作為表單的初始值使用。 + +雖然這個問題表面上看起來很簡單,但背後可能存在一些您尚未考慮到的複雜性。 + +舉例來說,您可能希望在資料載入時顯示載入動畫,或是需要優雅地處理錯誤情況。同樣地,您可能也會想尋找快取資料的方法,以避免每次渲染表單時都需要重新取得資料。 + +雖然我們可以從頭實作這些功能,但最終結果可能會與我們維護的另一個專案 [TanStack Query](https://tanstack.com/query) 非常相似。 + +因此,本指南將展示如何結合使用 TanStack Form 與 TanStack Query 來達成預期的行為。 + +## 基本用法 + +```svelte + + +{#if $isLoading} +

載入中...

+{:else} + +{/if} +``` + +這段程式碼會在資料載入完成前顯示載入提示,待資料取得後,便會以取得的資料作為初始值來渲染表單。 diff --git a/docs/zh-hant/framework/svelte/guides/basic-concepts.md b/docs/zh-hant/framework/svelte/guides/basic-concepts.md new file mode 100644 index 000000000..611f79f6d --- /dev/null +++ b/docs/zh-hant/framework/svelte/guides/basic-concepts.md @@ -0,0 +1,289 @@ +--- +source-updated-at: '2025-04-24T18:50:42.000Z' +translation-updated-at: '2025-04-25T20:48:34.853Z' +id: basic-concepts +title: 基本概念 +--- +本頁介紹 `@tanstack/svelte-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更有效地理解與使用此函式庫。 + +## 表單選項 (Form Options) + +您可以使用 `formOptions` 函式建立表單選項,以便在多個表單之間共享配置。 + +範例: + +```ts +const formOpts = formOptions({ + defaultValues: { + firstName: '', + lastName: '', + hobbies: [], + } as Person, +}) +``` + +## 表單實例 (Form Instance) + +表單實例 (Form Instance) 是一個代表單一表單的物件,提供操作表單的方法與屬性。您可以使用 `createForm` 函式建立表單實例。此函式接受包含 `onSubmit` 函式的物件,該函式會在表單提交時被呼叫。 + +```ts +const form = createForm(() => ({ + ...formOpts, + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, +})) +``` + +您也可以不使用 `formOptions` 直接建立表單實例: + +```ts +const form = createForm(() => ({ + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, + defaultValues: { + firstName: '', + lastName: '', + hobbies: [], + }, +})) +``` + +## 欄位 (Field) + +欄位 (Field) 代表單一表單輸入元素,例如文字輸入框或核取方塊。欄位是透過表單實例提供的 `form.Field` 元件建立。該元件接受 `name` 屬性 (應與表單預設值中的鍵名匹配) 和 `children` 屬性 (這是一個接收欄位物件作為參數的渲染函式)。 + +範例: + +```svelte + + {#snippet children(field)} + field.handleChange(e.target.value)} + /> + {/snippet} + +``` + +## 欄位狀態 (Field State) + +每個欄位都有自身的狀態,包含當前值、驗證狀態、錯誤訊息和其他元資料。您可以透過 `field.state` 屬性存取欄位狀態。 + +範例: + +```ts +const { + value, + meta: { errors, isValidating }, +} = field.state +``` + +有三種欄位狀態對於觀察使用者互動特別有用:當使用者點擊/切換到欄位時會標記為 _"touched"_、在值被修改前保持 _"pristine"_、值變更後則標記為 _"dirty"_。您可以透過以下標誌檢查這些狀態: + +```ts +const { isTouched, isPristine, isDirty } = field.state.meta +``` + +![欄位狀態](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/field-states.png) + +## 欄位 API (Field API) + +欄位 API (Field API) 是建立欄位時傳遞給渲染函式的物件,提供操作欄位狀態的方法。 + +範例: + +```svelte + field.handleChange(e.target.value)} +/> +``` + +## 驗證 (Validation) + +`@tanstack/svelte-form` 原生支援同步與非同步驗證。驗證函式可透過 `validators` 屬性傳遞給 `form.Field` 元件。 + +範例: + +```svelte + + !value + ? '必須填寫名字' + : value.length < 3 + ? '名字至少需要 3 個字元' + : undefined, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value.includes('error') && '名字中不能包含 "error"' + }, + }} +> + {#snippet children(field)} + field.handleChange(e.target.value)} + /> +

{field.state.meta.errors[0]}

+ {/snippet} +
+``` + +## 使用標準結構描述函式庫驗證 (Validation with Standard Schema Libraries) + +除了手動驗證選項外,我們也支援 [Standard Schema](https://github.com/standard-schema/standard-schema) 規範。 + +您可以使用任何實作此規範的函式庫定義結構描述,並將其傳遞給表單或欄位驗證器。 + +支援的函式庫包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +```svelte + + + { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return !value.includes('error') + }, + { + message: '名字中不能包含 "error"', + }, + ), + }} +> + {#snippet children(field)} + field.handleChange(e.target.value)} + /> +

{field.state.meta.errors[0]}

+ {/snippet} +
+``` + +## 響應式 (Reactivity) + +`@tanstack/svelte-form` 提供多種訂閱表單與欄位狀態變更的方式,最值得注意的是 `form.useStore` 鉤子 (hook) 和 `form.Subscribe` 元件。這些方法讓您可以透過僅在必要時更新元件來優化表單的渲染效能。 + +範例: + +```svelte + + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} +> + {#snippet children(state)} + + {/snippet} + +``` + +## 陣列欄位 (Array Fields) + +陣列欄位 (Array Fields) 讓您能管理表單中的值列表,例如興趣愛好清單。您可以使用 `form.Field` 元件並設定 `mode="array"` 屬性來建立陣列欄位。 + +操作陣列欄位時,可使用 `pushValue`、`removeValue`、`swapValues` 和 `moveValue` 方法來新增、移除和交換陣列中的值。 + +範例: + +```svelte + + {#snippet children(hobbiesField)} +
+ 興趣愛好 +
+ {#each hobbiesField.state.value as _, i} +
+ + {#snippet children(field)} +
+ + field.handleChange(e.target.value)} + /> + +
+ {/snippet} +
+ + {#snippet children(field)} +
+ + field.handleChange(e.target.value)} + /> +
+ {/snippet} +
+
+ {:else} + 未找到興趣愛好。 + {/each} +
+ +
+ {/snippet} +
+``` + +以上是 `@tanstack/svelte-form` 函式庫中使用的基本概念與術語。理解這些概念將幫助您更有效地使用此函式庫,輕鬆建立複雜的表單。 diff --git a/docs/zh-hant/framework/svelte/guides/linked-fields.md b/docs/zh-hant/framework/svelte/guides/linked-fields.md new file mode 100644 index 000000000..b02581d2c --- /dev/null +++ b/docs/zh-hant/framework/svelte/guides/linked-fields.md @@ -0,0 +1,80 @@ +--- +source-updated-at: '2025-04-24T18:50:42.000Z' +translation-updated-at: '2025-04-25T20:49:18.805Z' +id: linked-fields +title: 關聯欄位 +--- +## 連結兩個表單欄位 + +您可能會遇到需要將兩個欄位連結在一起的情況:當其中一個欄位需要根據另一個欄位值的變動進行驗證時。 +一個常見的使用情境是當您同時擁有 `password` 和 `confirm_password` 欄位時, +您會希望當 `confirm_password` 的值與 `password` 不符時顯示錯誤, +不論是哪個欄位觸發了值變更。 + +想像以下使用者流程: + +- 使用者更新確認密碼欄位 +- 使用者更新非確認密碼欄位 + +在這個範例中,表單仍會顯示錯誤, +因為「確認密碼」欄位的驗證尚未重新執行以標記為已接受。 + +為了解決這個問題,我們需要確保當密碼欄位更新時,「確認密碼」的驗證會被重新執行。 +您可以透過在 `confirm_password` 欄位添加 `onChangeListenTo` 屬性來實現。 + +```svelte + + +
+ + {#snippet children(field)} + + {/snippet} + + { + if (value !== fieldApi.form.getFieldValue('password')) { + return 'Passwords do not match' + } + return undefined + }, + }} + > + {#snippet children(field)} +
+ + {#each field.state.meta.errors as err} +
{err}
+ {/each} +
+ {/snippet} +
+
+``` + +同樣地,這也適用於 `onBlurListenTo` 屬性,該屬性會在欄位失去焦點時重新執行驗證。 diff --git a/docs/zh-hant/framework/svelte/guides/validation.md b/docs/zh-hant/framework/svelte/guides/validation.md new file mode 100644 index 000000000..a996ea9c1 --- /dev/null +++ b/docs/zh-hant/framework/svelte/guides/validation.md @@ -0,0 +1,407 @@ +--- +source-updated-at: '2025-04-24T18:50:42.000Z' +translation-updated-at: '2025-04-25T20:49:20.614Z' +id: form-validation +title: 表單驗證 +--- +TanStack Form 的核心功能之一是驗證 (validation) 概念。TanStack Form 讓驗證具有高度可自訂性: + +- 您可以控制驗證的時機(在變更時、輸入時、失焦時、提交時...) +- 驗證規則可以在欄位 (field) 層級或表單 (form) 層級定義 +- 驗證可以是同步或非同步(例如 API 呼叫的結果) + +## 驗證何時執行? + +由您決定!`` 元件接受一些回調函式作為 props,例如 `onChange` 或 `onBlur`。這些回調會接收欄位的當前值以及 fieldAPI 物件,讓您可以執行驗證。如果發現驗證錯誤,只需回傳錯誤訊息字串,該訊息就會出現在 `field.state.meta.errors` 中。 + +以下是一個範例: + +```svelte + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {#snippet children(field)} + + field.handleChange(e.target.valueAsNumber)} + /> + {#if field.state.meta.errors} + {field.state.meta.errors.join(', ')} + {/if} + {/snippet} + +``` + +在上面的範例中,驗證會在每次按鍵時執行(`onchange`)。如果我們想改為在欄位失焦時執行驗證,可以這樣修改程式碼: + +```svelte + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {#snippet children(field)} + + field.handleChange(e.target.valueAsNumber)} + /> + {#if field.state.meta.errors} + {field.state.meta.errors.join(', ')} + {/if} + {/snippet} + +``` + +因此,您可以透過實作所需的回調來控制驗證的時機。您甚至可以在不同時間執行不同的驗證: + +```svelte + + value < 13 ? 'You must be 13 to make an account' : undefined, + onBlur: ({ value }) => (value < 0 ? 'Invalid value' : undefined), + }} +> + {#snippet children(field)} + + field.handleChange(e.target.valueAsNumber)} + /> + {#if field.state.meta.errors} + {field.state.meta.errors.join(', ')} + {/if} + {/snippet} + +``` + +在上面的範例中,我們在不同時間(每次按鍵和欄位失焦時)對同一欄位進行不同的驗證。由於 `field.state.meta.errors` 是一個陣列,所有相關的錯誤都會在特定時間顯示。您也可以使用 `field.state.meta.errorMap` 根據驗證時機(onChange、onBlur 等)取得錯誤。更多關於顯示錯誤的資訊如下。 + +## 顯示錯誤 + +設定好驗證後,您可以將錯誤從陣列映射到 UI 中顯示: + +```svelte + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {#snippet children(field)} + + {#if field.state.meta.errors} + {field.state.meta.errors.join(', ')} + {/if} + {/snippet} + +``` + +或者使用 `errorMap` 屬性來存取特定的錯誤: + +```svelte + + value < 13 ? 'You must be 13 to make an account' : undefined, + }} +> + {#snippet children(field)} + + {#if field.state.meta.errorMap['onChange']} + {field.state.meta.errorMap['onChange']} + {/if} + {/snippet} + +``` + +值得一提的是,我們的 `errors` 陣列和 `errorMap` 會與驗證器回傳的型別匹配。這意味著: + +```svelte + (value < 13 ? { isOldEnough: false } : undefined), + }} +> + {#snippet children(field)} + + + + {#if field.state.meta.errorMap['onChange']?.isOldEnough} + The user is not old enough + {/if} + {/snippet} + +``` + +## 欄位層級與表單層級的驗證 + +如上所示,每個 `` 都透過 `onChange`、`onBlur` 等回調接受自己的驗證規則。也可以透過將類似的回調傳遞給 `createForm()` 鉤子,在表單層級(而不是逐個欄位)定義驗證規則。 + +範例: + +```svelte + + +
+ + {#if formErrorMap.current.onChange} +
+ There was an error on the form: {formErrorMap.current.onChange} +
+ {/if} + +
+``` + +## 非同步函式驗證 + +雖然我們認為大多數驗證會是同步的,但在許多情況下,透過網路呼叫或其他非同步操作進行驗證會很有用。 + +為此,我們提供了專用的 `onChangeAsync`、`onBlurAsync` 等方法來進行驗證: + +```svelte + { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return value < 13 ? 'You must be 13 to make an account' : undefined + }, + }} +> + {#snippet children(field)} + + field.handleChange(e.target.valueAsNumber)} + /> + {#if field.state.meta.errors} + {field.state.meta.errors.join(', ')} + {/if} + {/snippet} + +``` + +同步和非同步驗證可以共存。例如,可以在同一欄位上同時定義 `onBlur` 和 `onBlurAsync`: + +```svelte + (value < 13 ? 'You must be at least 13' : undefined), + onBlurAsync: async ({ value }) => { + const currentAge = await fetchCurrentAgeOnProfile() + return value < currentAge ? 'You can only increase the age' : undefined + }, + }} +> + {#snippet children(field)} + + field.handleChange(e.target.valueAsNumber)} + /> + {#if field.state.meta.errors} + {field.state.meta.errors.join(', ')} + {/if} + {/snippet} + +``` + +同步驗證方法(`onBlur`)會先執行,非同步方法(`onBlurAsync`)只有在同步方法(`onBlur`)成功時才會執行。若要改變此行為,請將 `asyncAlways` 選項設為 `true`,這樣無論同步方法的結果如何,非同步方法都會執行。 + +### 內建防抖動 (Debouncing) + +雖然非同步呼叫是針對資料庫進行驗證的好方法,但在每次按鍵時發送網路請求可能會對您的資料庫造成 DDoS 攻擊。 + +相反地,我們提供了一個簡單的方法來防抖動您的 `async` 呼叫,只需添加一個屬性: + +```svelte + { + // ... + }, + }} +> + + +``` + +這將以 500 毫秒的延遲防抖動每個非同步呼叫。您甚至可以針對每個驗證屬性覆寫此設定: + +```svelte + { + // ... + }, + onBlurAsync: async ({ value }) => { + // ... + }, + }} +> + + +``` + +> 這將每 1500 毫秒執行一次 `onChangeAsync`,而 `onBlurAsync` 將每 500 毫秒執行一次。 + +## 透過結構描述 (Schema) 函式庫進行驗證 + +雖然函式提供了更多靈活性和自訂驗證的方式,但它們可能有些冗長。為了解決這個問題,有一些函式庫提供了基於結構描述的驗證,使簡寫和型別嚴格的驗證變得更加容易。您也可以為整個表單定義一個結構描述並將其傳遞到表單層級,錯誤會自動傳播到欄位。 + +### 標準結構描述函式庫 + +TanStack Form 原生支援所有遵循 [Standard Schema 規範](https://github.com/standard-schema/standard-schema) 的函式庫,最著名的包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +_注意:_ 請確保使用結構描述函式庫的最新版本,因為舊版本可能尚未支援 Standard Schema。 + +要使用這些函式庫的結構描述,您可以像使用自訂函式一樣將其傳遞給 `validators` props: + +```svelte + + + + + +``` + +表單和欄位層級的非同步驗證也支援: + +```svelte + { + const currentAge = await fetchCurrentAgeOnProfile() + return value >= currentAge + }, + { + message: 'You can only increase the age', + }, + ), + }} +> + + +``` + +## 防止提交無效表單 + +`onChange`、`onBlur` 等回調也會在提交表單時執行,如果表單無效,提交會被阻止。 + +表單狀態物件有一個 `canSubmit` 標誌,當任何欄位無效且表單已被觸碰時,該標誌為 false(`canSubmit` 在表單被觸碰之前為 true,即使某些欄位根據其 `onChange`/`onBlur` props「技術上」無效)。 + +您可以透過 `form.Subscribe` 訂閱它,並使用該值來實現例如在表單無效時禁用提交按鈕(實際上,禁用按鈕不可訪問,請改用 `aria-disabled`)。 + +```svelte + + + + + + ({ + canSubmit: state.canSubmit, + isSubmitting: state.isSubmitting, + })} + children={(state) => ( + + )} +> + {#snippet children(state)} + + {/snippet} + +``` diff --git a/docs/zh-hant/framework/vue/guides/arrays.md b/docs/zh-hant/framework/vue/guides/arrays.md new file mode 100644 index 000000000..f1e451454 --- /dev/null +++ b/docs/zh-hant/framework/vue/guides/arrays.md @@ -0,0 +1,149 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:44:20.324Z' +id: arrays +title: 陣列 +--- +TanStack Form 支援將陣列 (array) 作為表單值,包含陣列中的子物件值。 + +## 基本用法 + +要使用陣列,您可以對陣列值使用 `field.state.value`,並搭配 [`solid-js` 的 `Index`](https://www.solidjs.com/tutorial/flow_index): + +```vue + + + +``` + +這會在每次對 `field` 執行 `pushValue` 時生成對應的插槽 (slot): + +```vue + +``` + +最後,您可以像這樣使用子欄位 (subfield): + +```vue + + + +``` + +## 完整範例 + +```vue + + + +``` diff --git a/docs/zh-hant/framework/vue/guides/async-initial-values.md b/docs/zh-hant/framework/vue/guides/async-initial-values.md new file mode 100644 index 000000000..09ed8de63 --- /dev/null +++ b/docs/zh-hant/framework/vue/guides/async-initial-values.md @@ -0,0 +1,60 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:43:43.073Z' +id: async-initial-values +title: 非同步初始值 +--- +假設您想從 API 獲取一些資料並將其作為表單的初始值。 + +雖然這個問題表面上看起來很簡單,但背後可能存在您尚未考慮到的隱藏複雜性。 + +舉例來說,您可能希望在資料獲取期間顯示載入動畫,或是需要優雅地處理錯誤情況。 + +同樣地,您也可能會尋找快取資料的方法,以避免每次表單渲染時都需要重新獲取。 + +雖然我們可以從頭實作這些功能,但最終結果可能會與我們維護的另一個專案 [TanStack Query](https://tanstack.com/query) 非常相似。 + +因此,本指南將展示如何結合使用 TanStack Form 與 TanStack Query 來實現所需行為。 + +## 基本用法 + +```vue + + + +``` + +這段程式碼會在資料獲取完成前顯示載入文字,之後才會渲染表單並使用獲取的資料作為初始值。 diff --git a/docs/zh-hant/framework/vue/guides/basic-concepts.md b/docs/zh-hant/framework/vue/guides/basic-concepts.md new file mode 100644 index 000000000..8843f2946 --- /dev/null +++ b/docs/zh-hant/framework/vue/guides/basic-concepts.md @@ -0,0 +1,351 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:40:57.676Z' +id: basic-concepts +title: 基本概念 +--- +本頁介紹 `@tanstack/vue-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更有效地理解與運用此函式庫。 + +## 表單選項 (Form Options) + +您可以使用 `formOptions` 函式建立表單選項,以便在多個表單之間共享配置。 + +範例: + +```ts +const formOpts = formOptions({ + defaultValues: { + firstName: '', + lastName: '', + hobbies: [], + } as Person, +}) +``` + +## 表單實例 (Form Instance) + +表單實例是一個代表單一表單的物件,提供操作表單的方法與屬性。您可以使用 `useForm` 函式建立表單實例。該函式接受包含 `onSubmit` 函式的物件,此函式會在表單提交時被呼叫。 + +```js +const form = useForm({ + ...formOpts, + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, +}) +``` + +您也可以不使用 `formOptions`,直接透過獨立的 `useForm` API 建立表單實例: + +```ts +const form = useForm({ + onSubmit: async ({ value }) => { + // 處理表單資料 + console.log(value) + }, + defaultValues: { + firstName: '', + lastName: '', + hobbies: [], + } as Person, +}) +``` + +## 欄位 (Field) + +欄位代表單一表單輸入元素,例如文字輸入框或核取方塊。欄位透過表單實例提供的 `form.Field` 元件建立。該元件接受 `name` 屬性,需與表單預設值中的鍵名匹配。同時也接受透過 `v-slot` 指令定義的作用域插槽,該插槽會接收一個 `field` 物件作為參數。 + +範例: + +```vue + +``` + +## 欄位狀態 (Field State) + +每個欄位都有自身的狀態,包含當前值、驗證狀態、錯誤訊息與其他元資料。您可以透過 `field.state` 屬性存取欄位狀態。 + +範例: + +```js +const { + value, + meta: { errors, isValidating }, +} = field.state +``` + +有三種欄位狀態能有效反映使用者互動行為:當使用者點擊/切換至欄位時標記為 _"touched"_、使用者未改變值時為 _"pristine"_、值被修改後則標記為 _"dirty"_。可透過以下標誌檢查這些狀態: + +```js +const { isTouched, isPristine, isDirty } = field.state.meta +``` + +![欄位狀態](https://raw.githubusercontent.com/TanStack/form/main/docs/assets/field-states.png) + +## 欄位 API (Field API) + +欄位 API 是由 `v-slot` 指令提供的作用域插槽物件。該插槽接收名為 `field` 的參數,提供操作欄位狀態的方法與屬性。 + +範例: + +```vue + +``` + +## 驗證 (Validation) + +`@tanstack/vue-form` 原生支援同步與非同步驗證。驗證函式可透過 `validators` 屬性傳遞給 `form.Field` 元件。 + +範例: + +```vue + +``` + +## 標準結構描述驗證 (Validation with Standard Schema Libraries) + +除了手動驗證選項外,我們也支援 [Standard Schema](https://github.com/standard-schema/standard-schema) 規範。 + +您可以使用任何實作此規範的函式庫定義結構描述,並將其傳遞給表單或欄位驗證器。 + +支援的函式庫包含: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +```vue + + + +``` + +## 響應式 (Reactivity) + +`@tanstack/vue-form` 提供多種訂閱表單與欄位狀態變更的方式,最主要是 `form.useStore` 方法與 `form.Subscribe` 元件。這些方法能讓您透過必要時才更新元件來優化表單渲染效能。 + +範例: + +```vue + + + +``` + +## 監聽器 (Listeners) + +`@tanstack/vue-form` 允許您對特定觸發事件做出反應,並「監聽」這些事件以執行副作用。 + +範例: + +```vue + +``` + +更多資訊請參閱 [監聽器](./listeners.md) + +注意:不建議使用 `form.useField` 方法實現響應式,因該方法設計為需謹慎使用於 `form.Field` 元件內。建議改用 `form.useStore`。 + +## 陣列欄位 (Array Fields) + +陣列欄位讓您能管理表單中的值列表,例如興趣清單。您可透過 `mode="array"` 屬性的 `form.Field` 元件建立陣列欄位。 + +操作陣列欄位時,可使用 `pushValue`、`removeValue`、`swapValues` 與 `moveValue` 方法來新增、移除與交換陣列中的值。 + +範例: + +```vue + +``` + +以上是 `@tanstack/vue-form` 函式庫中使用的基本概念與術語。理解這些概念將幫助您更有效率地運用此函式庫,輕鬆建立複雜的表單。 diff --git a/docs/zh-hant/framework/vue/guides/linked-fields.md b/docs/zh-hant/framework/vue/guides/linked-fields.md new file mode 100644 index 000000000..c78a706fb --- /dev/null +++ b/docs/zh-hant/framework/vue/guides/linked-fields.md @@ -0,0 +1,85 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:44:46.365Z' +id: linked-fields +title: 關聯欄位 +--- +## 連結兩個表單欄位 + +您可能會遇到需要將兩個欄位連結在一起的情況:當其中一個欄位需要根據另一個欄位的值變更進行驗證時。 +一個常見的使用情境是當您同時擁有 `password` 和 `confirm_password` 欄位時, +您希望當 `confirm_password` 的值與 `password` 不符時顯示錯誤, +無論是哪個欄位觸發了值變更。 + +想像以下使用者流程: + +- 使用者更新確認密碼欄位 +- 使用者更新原始密碼欄位 + +在此範例中,表單仍會顯示錯誤, +因為「確認密碼」欄位的驗證並未重新執行以標記為通過狀態。 + +為了解決這個問題,我們需要確保在密碼欄位更新時重新執行「確認密碼」的驗證。 +您可以透過在 `confirm_password` 欄位添加 `onChangeListenTo` 屬性來實現: + +```vue + + + +``` + +同樣地,此機制也適用於 `onBlurListenTo` 屬性,該屬性會在欄位失去焦點時重新執行驗證。 diff --git a/docs/zh-hant/framework/vue/guides/validation.md b/docs/zh-hant/framework/vue/guides/validation.md new file mode 100644 index 000000000..e4c2e48f2 --- /dev/null +++ b/docs/zh-hant/framework/vue/guides/validation.md @@ -0,0 +1,501 @@ +--- +source-updated-at: '2025-04-16T14:15:06.000Z' +translation-updated-at: '2025-04-25T20:43:23.474Z' +id: form-validation +title: 表單驗證 +--- +## 表單與欄位驗證 (Form and Field Validation) + +TanStack Form 的核心功能之一就是驗證機制。TanStack Form 讓驗證高度可自訂: + +- 您可以控制驗證時機 (變更時、輸入時、失焦時、提交時...) +- 驗證規則可以定義在欄位層級或表單層級 +- 驗證可以是同步或非同步 (例如 API 呼叫的結果) + +## 何時執行驗證? + +由您決定!`` 元件接受一些回調函式作為 props,例如 `onChange` 或 `onBlur`。這些回調會接收欄位的當前值以及 `fieldAPI` 物件,讓您可以執行驗證。如果發現驗證錯誤,只需回傳錯誤訊息字串,該訊息就會出現在 `field.state.meta.errors` 中。 + +以下是一個範例: + +```vue + +``` + +在上面的範例中,驗證在每次鍵盤輸入時執行 (`onChange`)。如果我們希望驗證在欄位失焦時執行,可以這樣修改程式碼: + +```vue + +``` + +因此,您可以通過實作所需的回調來控制驗證時機。您甚至可以在不同時間執行不同的驗證: + +```vue + +``` + +在上面的範例中,我們在同一欄位的不同時間點 (每次鍵盤輸入和欄位失焦時) 驗證不同內容。由於 `field.state.meta.errors` 是一個陣列,所有相關錯誤都會在特定時間顯示。您也可以使用 `field.state.meta.errorMap` 根據驗證時機 (onChange、onBlur 等) 取得錯誤。更多關於顯示錯誤的資訊請見下文。 + +## 顯示錯誤 + +設定好驗證後,您可以將錯誤從陣列映射到 UI 中顯示: + +```vue + +``` + +或者使用 `errorMap` 屬性來存取特定錯誤: + +```vue + +``` + +值得一提的是,我們的 `errors` 陣列和 `errorMap` 會匹配驗證器回傳的型別。這意味著: + +```vue + + + +``` + +## 欄位層級 vs 表單層級驗證 + +如上所示,每個 `` 通過 `onChange`、`onBlur` 等回調接受自己的驗證規則。也可以通過向 `useForm()` 函數傳遞類似的回調來定義表單層級的驗證規則 (而不是逐個欄位定義)。 + +範例: + +```vue + + + +``` + +## 非同步函數驗證 + +雖然我們認為大多數驗證會是同步的,但在許多情況下,使用網路呼叫或其他非同步操作進行驗證會很有用。 + +為此,我們提供了專用的 `onChangeAsync`、`onBlurAsync` 等方法來進行驗證: + +```vue + + + +``` + +同步和非同步驗證可以共存。例如,可以在同一欄位上同時定義 `onBlur` 和 `onBlurAsync`: + +```vue + + + +``` + +同步驗證方法 (`onBlur`) 會先執行,只有當同步方法 (`onBlur`) 成功時才會執行非同步方法 (`onBlurAsync`)。要改變此行為,請將 `asyncAlways` 選項設為 `true`,這樣無論同步方法的結果如何,都會執行非同步方法。 + +### 內建防抖 (Debouncing) + +雖然非同步呼叫是驗證資料庫的有效方式,但在每次鍵盤輸入時都發送網路請求可能會對您的資料庫造成 DDoS 攻擊。 + +相反地,我們提供了一個簡單的方法來防抖您的 `async` 呼叫,只需添加一個屬性: + +```vue + +``` + +這將以 500 毫秒的延遲防抖每個非同步呼叫。您甚至可以針對每個驗證屬性覆寫此設定: + +```vue + +``` + +這將每 1500 毫秒執行一次 `onChangeAsync`,而 `onBlurAsync` 將每 500 毫秒執行一次。 + +## 透過 Schema 函式庫驗證 + +雖然函數提供了更多靈活性和自訂驗證的能力,但它們可能有些冗長。為了解決這個問題,有一些函式庫提供了基於 schema 的驗證,使簡寫和型別嚴格的驗證變得更加容易。您還可以為整個表單定義一個 schema 並將其傳遞到表單層級,錯誤將自動傳播到欄位。 + +### 標準 Schema 函式庫 + +TanStack Form 原生支援所有遵循 [Standard Schema 規範](https://github.com/standard-schema/standard-schema) 的函式庫,最著名的包括: + +- [Zod](https://zod.dev/) +- [Valibot](https://valibot.dev/) +- [ArkType](https://arktype.io/) + +_注意:_ 請確保使用 schema 函式庫的最新版本,因為舊版本可能尚未支援 Standard Schema。 + +要使用這些函式庫的 schema,您可以像自訂函數一樣將它們傳遞給 `validators` props: + +```vue + + + +``` + +表單和欄位層級的非同步驗證也受支援: + +```vue + +``` + +如果您需要對 Standard Schema 驗證進行更多控制,可以像這樣將 Standard Schema 與回調函數結合使用: + +```vue + +``` + +## 防止提交無效表單 + +`onChange`、`onBlur` 等回調也會在表單提交時執行,如果表單無效,提交將被阻止。 + +表單狀態物件有一個 `canSubmit` 標誌,當任何欄位無效且表單已被觸碰時,該標誌為 false (`canSubmit` 在表單被觸碰前為 true,即使某些欄位根據其 `onChange`/`onBlur` props「技術上」無效)。 + +您可以通過 `form.Subscribe` 訂閱它,並使用該值來實現例如在表單無效時禁用提交按鈕 (實際上,禁用按鈕不可訪問,請改用 `aria-disabled`)。 + +```vue + + + +``` diff --git a/docs/zh-hant/framework/vue/quick-start.md b/docs/zh-hant/framework/vue/quick-start.md new file mode 100644 index 000000000..8dd9e2e8a --- /dev/null +++ b/docs/zh-hant/framework/vue/quick-start.md @@ -0,0 +1,48 @@ +--- +source-updated-at: '2025-03-31T17:05:18.000Z' +translation-updated-at: '2025-04-25T20:31:15.746Z' +id: quick-start +title: 快速開始 +--- +## 快速開始 + +使用 TanStack Form 最基本的入門步驟是建立一個表單並加入欄位。請注意,此範例尚未包含任何驗證或錯誤處理功能。 + +```vue + + + + +``` + +從這裡開始,您就可以準備探索 TanStack Form 的所有其他功能了! diff --git a/docs/zh-hant/framework/vue/reference/functions/usefield.md b/docs/zh-hant/framework/vue/reference/functions/usefield.md new file mode 100644 index 000000000..2db7d0126 --- /dev/null +++ b/docs/zh-hant/framework/vue/reference/functions/usefield.md @@ -0,0 +1,77 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:54:17.675Z' +id: useField +title: 函式 / useField +--- + + +# 函式: useField() + +```ts +function useField(opts): object +``` + +定義於: [packages/vue-form/src/useField.tsx:267](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L267) + +## 類型參數 + +• **TParentData** + +• **TName** *繼承自* `string` + +• **TData** + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 參數 + +### opts + +`UseFieldOptions`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> + +## 回傳值 + +`object` + +### api + +```ts +readonly api: FieldApi & VueFieldApi = fieldApi; +``` + +### state + +```ts +readonly state: Readonly, FieldState>> = fieldState; +``` diff --git a/docs/zh-hant/framework/vue/reference/functions/useform.md b/docs/zh-hant/framework/vue/reference/functions/useform.md new file mode 100644 index 000000000..4242ffa1c --- /dev/null +++ b/docs/zh-hant/framework/vue/reference/functions/useform.md @@ -0,0 +1,47 @@ +--- +source-updated-at: '2025-02-25T06:59:48.000Z' +translation-updated-at: '2025-04-25T20:54:40.204Z' +id: useForm +title: 函式 / useForm +--- + + +# 函式: useForm() + +```ts +function useForm(opts?): FormApi & VueFormApi +``` + +定義於: [packages/vue-form/src/useForm.tsx:195](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useForm.tsx#L195) + +## 型別參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TSubmitMeta** + +## 參數 + +### opts? + +`FormOptions`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> + +## 回傳值 + +`FormApi`\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> & [`VueFormApi`](../interfaces/vueformapi.md)\<`TParentData`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TSubmitMeta`\> diff --git a/docs/zh-hant/framework/vue/reference/index.md b/docs/zh-hant/framework/vue/reference/index.md new file mode 100644 index 000000000..99e3fc757 --- /dev/null +++ b/docs/zh-hant/framework/vue/reference/index.md @@ -0,0 +1,31 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:53:37.811Z' +id: '@tanstack/vue-form' +title: Vue 參考 +--- + + +# @tanstack/vue-form + +## 介面 (Interfaces) + +- [VueFieldApi](interfaces/vuefieldapi.md) +- [VueFormApi](interfaces/vueformapi.md) + +## 類型別名 (Type Aliases) + +- [FieldComponent](type-aliases/fieldcomponent.md) +- [FieldComponentBoundProps](type-aliases/fieldcomponentboundprops.md) +- [FieldComponentProps](type-aliases/fieldcomponentprops.md) +- [UseField](type-aliases/usefield.md) + +## 變數 (Variables) + +- [Field](variables/field.md) + +## 函式 (Functions) + +- [useField](functions/usefield.md) +- [useForm](functions/useform.md) +- [useStore](functions/usestore.md) diff --git a/docs/zh-hant/framework/vue/reference/type-aliases/fieldcomponent.md b/docs/zh-hant/framework/vue/reference/type-aliases/fieldcomponent.md new file mode 100644 index 000000000..3b115f12d --- /dev/null +++ b/docs/zh-hant/framework/vue/reference/type-aliases/fieldcomponent.md @@ -0,0 +1,55 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:55:00.403Z' +id: FieldComponent +title: 類型 / FieldComponent +--- +# 類型別名: FieldComponent()\ + +```ts +type FieldComponent = (props) => CreateComponentPublicInstanceWithMixins, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, PublicProps, {}, false, {}, SlotsType<{ + default: { + field: FieldApi; + state: FieldApi["state"]; + }; +}>>; +``` + +定義於: [packages/vue-form/src/useField.tsx:24](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L24) + +## 類型參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 參數 + +### props + +[`FieldComponentBoundProps`](fieldcomponentboundprops.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> & `EmitsToProps`\<`EmitsOptions`\> & `PublicProps` + +## 返回值 + +`CreateComponentPublicInstanceWithMixins`\<[`FieldComponentBoundProps`](fieldcomponentboundprops.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\>, \{\}, \{\}, \{\}, \{\}, `ComponentOptionsMixin`, `ComponentOptionsMixin`, `EmitsOptions`, `PublicProps`, \{\}, `false`, \{\}, `SlotsType`\<\{ + `default`: \{ + `field`: `FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\>; + `state`: `FieldApi`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\>\[`"state"`\]; + \}; + \}\>\> diff --git a/docs/zh-hant/framework/vue/reference/type-aliases/usefield.md b/docs/zh-hant/framework/vue/reference/type-aliases/usefield.md new file mode 100644 index 000000000..4b9517e59 --- /dev/null +++ b/docs/zh-hant/framework/vue/reference/type-aliases/usefield.md @@ -0,0 +1,77 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:54:58.157Z' +id: UseField +title: 類型 / UseField +--- +# 類型別名:UseField()\ + +```ts +type UseField = (opts) => object; +``` + +定義於:[packages/vue-form/src/useField.tsx:166](https://github.com/TanStack/form/blob/main/packages/vue-form/src/useField.tsx#L166) + +## 類型參數 + +• **TParentData** + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 類型參數 + +• **TName** *繼承自* `DeepKeys`\<`TParentData`\> + +• **TData** *繼承自* `DeepValue`\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 參數 + +### opts + +`UseFieldOptionsBound`\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> + +## 回傳值 + +`object` + +### api + +```ts +api: FieldApi & VueFieldApi; +``` + +### state + +```ts +state: Readonly["state"]>>; +``` diff --git a/docs/zh-hant/installation.md b/docs/zh-hant/installation.md new file mode 100644 index 000000000..8e54d2faf --- /dev/null +++ b/docs/zh-hant/installation.md @@ -0,0 +1,87 @@ +--- +source-updated-at: '2025-04-24T18:50:42.000Z' +translation-updated-at: '2025-04-25T20:31:22.201Z' +id: installation +title: 安裝 +--- +TanStack Form 相容於多種前端框架 (front-end frameworks),包括 React、Vue 和 Solid。要將 TanStack Form 與您選擇的框架搭配使用,請透過您偏好的套件管理工具安裝對應的轉接器 (adapter): + +### React 範例 + +```bash +# npm +$ npm i @tanstack/react-form +# pnpm +$ pnpm add @tanstack/react-form +# bun +$ bun add @tanstack/react-form +# yarn +$ yarn add @tanstack/react-form +``` + +### Vue 範例 + +```bash +# npm +$ npm i @tanstack/vue-form +# pnpm +$ pnpm add @tanstack/vue-form +# bun +$ bun add @tanstack/vue-form +# yarn +$ yarn add @tanstack/vue-form +``` + +### Angular 範例 + +```bash +# npm +$ npm i @tanstack/angular-form +# pnpm +$ pnpm add @tanstack/angular-form +# bun +$ bun add @tanstack/angular-form +# yarn +$ yarn add @tanstack/angular-form +``` + +### Solid 範例 + +```bash +# npm +$ npm i @tanstack/solid-form +# pnpm +$ pnpm add @tanstack/solid-form +# bun +$ bun add @tanstack/solid-form +# yarn +$ yarn add @tanstack/solid-form +``` + +### Lit 範例 + +```bash +# npm +$ npm i @tanstack/lit-form +# pnpm +$ pnpm add @tanstack/lit-form +# bun +$ bun add @tanstack/lit-form +# yarn +$ yarn add @tanstack/lit-form +``` + +### Svelte 範例 + +```bash +# npm +$ npm i @tanstack/svelte-form +# pnpm +$ pnpm add @tanstack/svelte-form +# bun +$ bun add @tanstack/svelte-form +# yarn +$ yarn add @tanstack/svelte-form +``` + +> 根據您的環境,可能需要加入 polyfills。如果您需要支援舊版瀏覽器,請自行從 `node_modules` 轉譯 (transpile) 此函式庫。 diff --git a/docs/zh-hant/overview.md b/docs/zh-hant/overview.md new file mode 100644 index 000000000..48e54f21c --- /dev/null +++ b/docs/zh-hant/overview.md @@ -0,0 +1,143 @@ +--- +source-updated-at: '2025-03-04T11:48:41.000Z' +translation-updated-at: '2025-04-25T20:31:46.664Z' +id: overview +title: 概述 +--- +TanStack Form 是處理網頁應用程式中表單的終極解決方案,提供強大且靈活的表單管理方法。它具備一流的 TypeScript 支援、無頭 UI 元件 (headless UI components) 以及框架無關的設計 (framework-agnostic design),能簡化表單處理流程,並確保在不同前端框架 (front-end frameworks) 間提供無縫的使用體驗。 + +## 動機 + +大多數網頁框架 (web frameworks) 並未提供全面的表單處理解決方案,導致開發者必須自行建立客製化實作或依賴功能較弱的函式庫。這通常會造成一致性不足、效能不佳以及開發時間增加等問題。TanStack Form 旨在透過提供一個功能強大且易於使用的全方位表單管理解決方案,來應對這些挑戰。 + +使用 TanStack Form,開發者可以解決以下常見的表單相關挑戰: + +- 響應式資料綁定 (Reactive data binding) 與狀態管理 (state management) +- 複雜的驗證 (validation) 與錯誤處理 (error handling) +- 無障礙性 (accessibility) 與響應式設計 (responsive design) +- 國際化 (internationalization) 與本地化 (localization) +- 跨平台相容性 (cross-platform compatibility) 與自訂樣式 (custom styling) + +透過為這些挑戰提供完整的解決方案,TanStack Form 讓開發者能夠輕鬆建構穩健且使用者友善的表單。 + +## 別光說不練,直接看程式碼吧! + +在以下範例中,您可以看到 TanStack Form 與 React 框架轉接器 (framework adapter) 的實際運作: + +[在 CodeSandbox 中開啟](https://codesandbox.io/s/github/tanstack/form/tree/main/examples/react/simple) + +```tsx +import * as React from 'react' +import { createRoot } from 'react-dom/client' +import { useForm } from '@tanstack/react-form' +import type { AnyFieldApi } from '@tanstack/react-form' + +function FieldInfo({ field }: { field: AnyFieldApi }) { + return ( + <> + {field.state.meta.isTouched && field.state.meta.errors.length ? ( + {field.state.meta.errors.join(', ')} + ) : null} + {field.state.meta.isValidating ? 'Validating...' : null} + + ) +} + +export default function App() { + const form = useForm({ + defaultValues: { + firstName: '', + lastName: '', + }, + onSubmit: async ({ value }) => { + // Do something with form data + console.log(value) + }, + }) + + return ( +
+

Simple Form Example

+
{ + e.preventDefault() + e.stopPropagation() + form.handleSubmit() + }} + > +
+ {/* A type-safe field component*/} + + !value + ? 'A first name is required' + : value.length < 3 + ? 'First name must be at least 3 characters' + : undefined, + onChangeAsyncDebounceMs: 500, + onChangeAsync: async ({ value }) => { + await new Promise((resolve) => setTimeout(resolve, 1000)) + return ( + value.includes('error') && 'No "error" allowed in first name' + ) + }, + }} + children={(field) => { + // Avoid hasty abstractions. Render props are great! + return ( + <> + + field.handleChange(e.target.value)} + /> + + + ) + }} + /> +
+
+ ( + <> + + field.handleChange(e.target.value)} + /> + + + )} + /> +
+ [state.canSubmit, state.isSubmitting]} + children={([canSubmit, isSubmitting]) => ( + + )} + /> + +
+ ) +} + +const rootElement = document.getElementById('root')! + +createRoot(rootElement).render() +``` + +## 既然你這麼說,那接下來呢? + +- 透過我們詳盡的[入門指南](../installation)和[API 參考文件](../reference/classes/formapi),按照自己的步調學習 TanStack Form diff --git a/docs/zh-hant/philosophy.md b/docs/zh-hant/philosophy.md new file mode 100644 index 000000000..24b96cc9f --- /dev/null +++ b/docs/zh-hant/philosophy.md @@ -0,0 +1,77 @@ +--- +source-updated-at: '2025-04-16T08:45:06.000Z' +translation-updated-at: '2025-04-25T20:31:39.116Z' +id: philosophy +title: 設計理念 +--- +每個成熟的專案都應該有其指導開發的核心哲學。若缺乏核心理念,開發過程可能會陷入無止境的決策困境,最終導致 API 設計薄弱。 + +本文概述了驅動 TanStack Form 開發與功能設計的核心原則。 + +## 升級統一化的 API + +API 設計必然伴隨權衡取捨。因此,開發者常會想透過不同 API 來提供各種權衡方案。但這可能導致 API 碎片化,增加學習與使用難度。 + +雖然這意味著較高的學習曲線,但能讓您無需糾結該選用哪種 API,也不會在切換 API 時增加認知負擔。 + +## 表單需要靈活性 + +TanStack Form 的設計強調靈活性與可定制化。雖然多數表單可能遵循相似模式,但總會存在例外情況——尤其是當表單成為應用核心元件時。 + +因此,TanStack Form 支援多種驗證方式: + +- **時機定制**:可在失焦時、變更時、提交時,甚至掛載時進行驗證 +- **驗證策略**:可針對單一欄位、整個表單或欄位子集進行驗證 +- **自訂驗證邏輯**:可自行編寫驗證邏輯,或使用 [Zod](https://zod.dev/) 或 [Valibot](https://valibot.dev/) 等函式庫 +- **自訂錯誤訊息**:可透過驗證器返回任意物件來定制每個欄位的錯誤訊息 +- **非同步驗證**:支援非同步欄位驗證,並自動處理防抖與取消等常見工具 + +## 受控式設計的優勢 + +在「受控與非受控輸入」的熱門議題中,TanStack Form 堅定採用受控式設計。 + +這帶來諸多優勢: + +- **可預測性**:隨時掌握表單狀態 +- **易於測試**:透過傳入值與斷言輸出即可輕鬆測試表單 +- **非 DOM 支援**:可搭配 React Native、Three.js 框架轉接器或任何渲染器使用 +- **強化條件邏輯**:能根據表單狀態輕鬆顯示/隱藏欄位 +- **除錯便利**:可輕鬆將表單狀態輸出至控制台進行除錯 + +## 避免泛型參數 + +使用 TanStack Form 時,您不應需要傳遞泛型參數或使用內部型別。這是因為函式庫設計會從運行時預設值推斷所有型別。 + +當編寫足夠正確的 TanStack Form 程式碼時,除了對運行時值的型別轉換外,您應該無法區分 JavaScript 與 TypeScript 的使用差異。 + +不建議寫法: +```typescript +useForm() +``` + +建議寫法: +```typescript +interface Person { + name: string + age: number +} + +const defaultPerson: Person = { name: 'Bill Luo', age: 24 } + +useForm({ + defaultValues: defaultPerson, +}) +``` + +## 函式庫的解放力量 + +TanStack Form 的主要目標之一,是讓您能將其封裝進自己的元件系統或設計系統中。 + +為支援此目標,我們提供多種工具來簡化自訂元件與鉤子的開發: + +```typescript +// 從您的函式庫匯出已預綁定表單元件的工具 +export const { useAppForm, withForm } = createFormHook(/* options */) +``` + +若不這麼做,將大幅增加應用程式的樣板程式碼,並降低表單的一致性和使用者體驗。 diff --git a/docs/zh-hant/reference/classes/fieldapi.md b/docs/zh-hant/reference/classes/fieldapi.md new file mode 100644 index 000000000..e59d8ae95 --- /dev/null +++ b/docs/zh-hant/reference/classes/fieldapi.md @@ -0,0 +1,523 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:51:32.206Z' +id: FieldApi +title: 類別 / FieldApi +--- +# 類別: FieldApi\ + +定義於: [packages/form-core/src/FieldApi.ts:855](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L855) + +一個用於管理表單欄位的 API 類別。 + +通常您不需要直接建立新的 `FieldApi` 實例。 +相反地,您會使用框架的鉤子/函數如 `useField` 或 `createField` +來為您建立一個使用您框架反應式模型的新實例。 +然而,如果需要手動建立新實例,您可以通過呼叫 +`new FieldApi` 建構函式來實現。 + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> + +• **TData** *繼承自* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 建構函式 + +### new FieldApi() + +```ts +new FieldApi(opts): FieldApi +``` + +定義於: [packages/form-core/src/FieldApi.ts:986](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L986) + +初始化一個新的 `FieldApi` 實例。 + +#### 參數 + +##### opts + +[`FieldApiOptions`](../interfaces/fieldapioptions.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> + +#### 回傳 + +[`FieldApi`](fieldapi.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`, `TFormOnServer`, `TParentSubmitMeta`\> + +## 屬性 + +### form + +```ts +form: FormApi; +``` + +定義於: [packages/form-core/src/FieldApi.ts:899](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L899) + +對表單 API 實例的參考。 + +*** + +### name + +```ts +name: DeepKeys; +``` + +定義於: [packages/form-core/src/FieldApi.ts:923](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L923) + +欄位名稱。 + +*** + +### options + +```ts +options: FieldApiOptions; +``` + +定義於: [packages/form-core/src/FieldApi.ts:927](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L927) + +欄位選項。 + +*** + +### store + +```ts +store: Derived>; +``` + +定義於: [packages/form-core/src/FieldApi.ts:951](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L951) + +欄位狀態儲存。 + +*** + +### timeoutIds + +```ts +timeoutIds: object; +``` + +定義於: [packages/form-core/src/FieldApi.ts:978](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L978) + +#### listeners + +```ts +listeners: Record; +``` + +#### validations + +```ts +validations: Record; +``` + +## 存取器 + +### state + +#### Get 簽名 + +```ts +get state(): FieldState +``` + +定義於: [packages/form-core/src/FieldApi.ts:975](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L975) + +當前欄位狀態。 + +##### 回傳 + +[`FieldState`](../type-aliases/fieldstate.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`\> + +## 方法 + +### getInfo() + +```ts +getInfo(): FieldInfo +``` + +定義於: [packages/form-core/src/FieldApi.ts:1239](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1239) + +取得欄位資訊物件。 + +#### 回傳 + +[`FieldInfo`](../type-aliases/fieldinfo.md)\<`TParentData`\> + +*** + +### getMeta() + +```ts +getMeta(): FieldMeta +``` + +定義於: [packages/form-core/src/FieldApi.ts:1207](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1207) + +#### 回傳 + +[`FieldMeta`](../type-aliases/fieldmeta.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TFormOnMount`, `TFormOnChange`, `TFormOnChangeAsync`, `TFormOnBlur`, `TFormOnBlurAsync`, `TFormOnSubmit`, `TFormOnSubmitAsync`\> + +*** + +### ~~getValue()~~ + +```ts +getValue(): TData +``` + +定義於: [packages/form-core/src/FieldApi.ts:1192](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1192) + +取得當前欄位值。 + +#### 回傳 + +`TData` + +#### 已棄用 + +請改用 `field.state.value`。 + +*** + +### handleBlur() + +```ts +handleBlur(): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1651](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1651) + +處理 blur 事件。 + +#### 回傳 + +`void` + +*** + +### handleChange() + +```ts +handleChange(updater): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1644](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1644) + +處理 change 事件。 + +#### 參數 + +##### updater + +[`Updater`](../type-aliases/updater.md)\<`TData`\> + +#### 回傳 + +`void` + +*** + +### insertValue() + +```ts +insertValue( + index, + value, + opts?): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1256](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1256) + +在指定索引處插入值,並將後續值向右移動。 + +#### 參數 + +##### index + +`number` + +##### value + +`TData` *繼承自* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳 + +`void` + +*** + +### mount() + +```ts +mount(): () => void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1082](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1082) + +將欄位實例掛載到表單。 + +#### 回傳 + +`Function` + +##### 回傳 + +`void` + +*** + +### moveValue() + +```ts +moveValue( + aIndex, + bIndex, + opts?): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1300](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1300) + +將第一個指定索引處的值移動到第二個指定索引處。 + +#### 參數 + +##### aIndex + +`number` + +##### bIndex + +`number` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳 + +`void` + +*** + +### parseValueWithSchema() + +```ts +parseValueWithSchema(schema): + | undefined + | StandardSchemaV1Issue[] +``` + +定義於: [packages/form-core/src/FieldApi.ts:1686](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1686) + +使用給定的 schema 解析欄位值並回傳 +問題(如果有的話)。此方法不會設定任何內部錯誤。 + +#### 參數 + +##### schema + +[`StandardSchemaV1`](../type-aliases/standardschemav1.md)\<`TData`, `unknown`\> + +用於解析此欄位值的標準 schema。 + +#### 回傳 + + \| `undefined` + \| [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[] + +*** + +### parseValueWithSchemaAsync() + +```ts +parseValueWithSchemaAsync(schema): Promise< + | undefined +| StandardSchemaV1Issue[]> +``` + +定義於: [packages/form-core/src/FieldApi.ts:1698](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1698) + +使用給定的 schema 解析欄位值並回傳 +問題(如果有的話)。此方法不會設定任何內部錯誤。 + +#### 參數 + +##### schema + +[`StandardSchemaV1`](../type-aliases/standardschemav1.md)\<`TData`, `unknown`\> + +用於解析此欄位值的標準 schema。 + +#### 回傳 + +`Promise`\< + \| `undefined` + \| [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[]\> + +*** + +### pushValue() + +```ts +pushValue(value, opts?): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1244](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1244) + +將新值推入欄位。 + +#### 參數 + +##### value + +`TData` *繼承自* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳 + +`void` + +*** + +### removeValue() + +```ts +removeValue(index, opts?): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1282](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1282) + +移除指定索引處的值。 + +#### 參數 + +##### index + +`number` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳 + +`void` + +*** + +### replaceValue() + +```ts +replaceValue( + index, + value, + opts?): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1269](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1269) + +替換指定索引處的值。 + +#### 參數 + +##### index + +`number` + +##### value + +`TData` *繼承自* `any`[] ? `TData`\<`TData`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳 + +`void` + +*** + +### setErrorMap() + +```ts +setErrorMap(errorMap): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1668](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1668) + +更新欄位的 errorMap + +#### 參數 + +##### errorMap + +`ValidationErrorMap` + +#### 回傳 + +`void` + +*** + +### setMeta() + +```ts +setMeta(updater): void +``` + +定義於: [packages/form-core/src/FieldApi.ts:1212](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L1212) + +設定欄位元數據。 + +#### 參數 + +##### updater + +[`Updater`](../type-aliases/updater.md)\ diff --git a/docs/zh-hant/reference/classes/formapi.md b/docs/zh-hant/reference/classes/formapi.md new file mode 100644 index 000000000..c6f81f8c7 --- /dev/null +++ b/docs/zh-hant/reference/classes/formapi.md @@ -0,0 +1,614 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:51:34.117Z' +id: FormApi +title: 類別 / FormApi +--- +# 類別: FormApi\ + +定義於: [packages/form-core/src/FormApi.ts:765](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L765) + +代表表單 API 的類別。負責處理表單狀態的邏輯與互動。 + +通常您不需要直接建立新的 `FormApi` 實例。相反地,您會使用框架提供的鉤子/函式如 `useForm` 或 `createForm` 來建立一個使用您框架反應式模型的新實例。然而,如果需要手動建立新實例,可以通過呼叫 `new FormApi` 建構函式來實現。 + +## 型別參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TSubmitMeta** = `never` + +## 建構函式 + +### new FormApi() + +```ts +new FormApi(opts?): FormApi +``` + +定義於: [packages/form-core/src/FormApi.ts:836](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L836) + +使用給定的表單選項建構一個新的 `FormApi` 實例。 + +#### 參數 + +##### opts? + +[`FormOptions`](../interfaces/formoptions.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +#### 回傳值 + +[`FormApi`](formapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +## 屬性 + +### baseStore + +```ts +baseStore: Store>; +``` + +定義於: [packages/form-core/src/FormApi.ts:792](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L792) + +*** + +### fieldInfo + +```ts +fieldInfo: Record, FieldInfo>; +``` + +定義於: [packages/form-core/src/FormApi.ts:822](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L822) + +表單中每個欄位的欄位資訊記錄。 + +*** + +### fieldMetaDerived + +```ts +fieldMetaDerived: Derived, AnyFieldMeta>>; +``` + +定義於: [packages/form-core/src/FormApi.ts:805](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L805) + +*** + +### options + +```ts +options: FormOptions = {}; +``` + +定義於: [packages/form-core/src/FormApi.ts:780](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L780) + +表單的選項。 + +*** + +### store + +```ts +store: Derived>; +``` + +定義於: [packages/form-core/src/FormApi.ts:806](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L806) + +## 存取器 + +### state + +#### Get 簽名 + +```ts +get state(): FormState +``` + +定義於: [packages/form-core/src/FormApi.ts:824](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L824) + +##### 回傳值 + +[`FormState`](../interfaces/formstate.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`\> + +## 方法 + +### deleteField() + +```ts +deleteField(field): void +``` + +定義於: [packages/form-core/src/FormApi.ts:1911](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1911) + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +#### 回傳值 + +`void` + +*** + +### getAllErrors() + +```ts +getAllErrors(): object +``` + +定義於: [packages/form-core/src/FormApi.ts:2149](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L2149) + +回傳表單與欄位層級的錯誤 + +#### 回傳值 + +`object` + +##### fields + +```ts +fields: Record, { + errorMap: ValidationErrorMap; + errors: unknown[]; +}>; +``` + +##### form + +```ts +form: object; +``` + +###### form.errorMap + +```ts +errorMap: FormValidationErrorMap, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormAsyncValidateOrFn>; +``` + +###### form.errors + +```ts +errors: ( + | UnwrapFormValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormAsyncValidateOrFn)[]; +``` + +*** + +### getFieldInfo() + +```ts +getFieldInfo(field): FieldInfo +``` + +定義於: [packages/form-core/src/FormApi.ts:1825](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1825) + +取得指定欄位的欄位資訊。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +#### 回傳值 + +[`FieldInfo`](../type-aliases/fieldinfo.md)\<`TFormData`\> + +*** + +### getFieldMeta() + +```ts +getFieldMeta(field): undefined | AnyFieldMeta +``` + +定義於: [packages/form-core/src/FormApi.ts:1816](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1816) + +取得指定欄位的中繼資料。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +#### 回傳值 + +`undefined` \| [`AnyFieldMeta`](../type-aliases/anyfieldmeta.md) + +*** + +### getFieldValue() + +```ts +getFieldValue(field): DeepValue +``` + +定義於: [packages/form-core/src/FormApi.ts:1809](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1809) + +取得指定欄位的值。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +#### 回傳值 + +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\> + +*** + +### handleSubmit() + +#### 呼叫簽名 + +```ts +handleSubmit(): Promise +``` + +定義於: [packages/form-core/src/FormApi.ts:1711](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1711) + +處理表單提交,執行驗證,並呼叫適當的 onSubmit 或 onSubmitInvalid 回呼函式。 + +##### 回傳值 + +`Promise`\<`void`\> + +#### 呼叫簽名 + +```ts +handleSubmit(submitMeta): Promise +``` + +定義於: [packages/form-core/src/FormApi.ts:1712](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1712) + +處理表單提交,執行驗證,並呼叫適當的 onSubmit 或 onSubmitInvalid 回呼函式。 + +##### 參數 + +###### submitMeta + +`TSubmitMeta` + +##### 回傳值 + +`Promise`\<`void`\> + +*** + +### insertFieldValue() + +```ts +insertFieldValue( + field, + index, + value, +opts?): Promise +``` + +定義於: [packages/form-core/src/FormApi.ts:1950](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1950) + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +##### index + +`number` + +##### value + +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\> *繼承自* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳值 + +`Promise`\<`void`\> + +*** + +### mount() + +```ts +mount(): () => void +``` + +定義於: [packages/form-core/src/FormApi.ts:1141](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1141) + +#### 回傳值 + +`Function` + +##### 回傳值 + +`void` + +*** + +### moveFieldValues() + +```ts +moveFieldValues( + field, + index1, + index2, + opts?): void +``` + +定義於: [packages/form-core/src/FormApi.ts:2074](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L2074) + +將陣列欄位中第一個指定索引的值移動到第二個指定索引。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +##### index1 + +`number` + +##### index2 + +`number` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳值 + +`void` + +*** + +### parseValuesWithSchema() + +```ts +parseValuesWithSchema(schema): + | undefined + | { + fields: Record; + form: Record; +} +``` + +定義於: [packages/form-core/src/FormApi.ts:2209](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L2209) + +使用給定的標準結構描述解析表單值並回傳問題(如果有)。此方法不會設定任何內部錯誤。 + +#### 參數 + +##### schema + +[`StandardSchemaV1`](../type-aliases/standardschemav1.md)\<`TFormData`, `unknown`\> + +用來解析表單值的標準結構描述。 + +#### 回傳值 + + \| `undefined` + \| \{ + `fields`: `Record`\<`string`, [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[]\>; + `form`: `Record`\<`string`, [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[]\>; + \} + +*** + +### parseValuesWithSchemaAsync() + +```ts +parseValuesWithSchemaAsync(schema): Promise< + | undefined + | { + fields: Record; + form: Record; +}> +``` + +定義於: [packages/form-core/src/FormApi.ts:2221](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L2221) + +使用給定的標準結構描述解析表單值並回傳問題(如果有)。此方法不會設定任何內部錯誤。 + +#### 參數 + +##### schema + +[`StandardSchemaV1`](../type-aliases/standardschemav1.md)\<`TFormData`, `unknown`\> + +用來解析表單值的標準結構描述。 + +#### 回傳值 + +`Promise`\< + \| `undefined` + \| \{ + `fields`: `Record`\<`string`, [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[]\>; + `form`: `Record`\<`string`, [`StandardSchemaV1Issue`](../interfaces/standardschemav1issue.md)[]\>; + \}\> + +*** + +### pushFieldValue() + +```ts +pushFieldValue( + field, + value, + opts?): void +``` + +定義於: [packages/form-core/src/FormApi.ts:1935](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1935) + +將值推入陣列欄位。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +##### value + +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\> *繼承自* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳值 + +`void` + +*** + +### removeFieldValue() + +```ts +removeFieldValue( + field, + index, +opts?): Promise +``` + +定義於: [packages/form-core/src/FormApi.ts:2008](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L2008) + +從陣列欄位的指定索引移除值。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +##### index + +`number` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳值 + +`Promise`\<`void`\> + +*** + +### replaceFieldValue() + +```ts +replaceFieldValue( + field, + index, + value, +opts?): Promise +``` + +定義於: [packages/form-core/src/FormApi.ts:1982](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1982) + +替換陣列欄位中指定索引的值。 + +#### 型別參數 + +• **TField** *繼承自* `string` + +#### 參數 + +##### field + +`TField` + +##### index + +`number` + +##### value + +[`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\> *繼承自* `any`[] ? `any`[] & [`DeepValue`](../type-aliases/deepvalue.md)\<`TFormData`, `TField`\>\[`number`\] : `never` + +##### opts? + +`UpdateMetaOptions` + +#### 回傳值 + +`Promise`\<`void`\> + +*** + +### reset() + +```ts +reset(values?, opts?): void +``` + +定義於: [packages/form-core/src/FormApi.ts:1229](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L1229) + +將表單狀態重置為預設值。 +如果提供了值,表單將重置為這些值並 diff --git a/docs/zh-hant/reference/functions/formoptions.md b/docs/zh-hant/reference/functions/formoptions.md new file mode 100644 index 000000000..ffb172c57 --- /dev/null +++ b/docs/zh-hant/reference/functions/formoptions.md @@ -0,0 +1,27 @@ +--- +source-updated-at: '2025-03-08T10:02:40.000Z' +translation-updated-at: '2025-04-25T20:49:04.818Z' +id: formOptions +title: 函式 / formOptions +--- +# 函式: formOptions() + +```ts +function formOptions(defaultOpts): T +``` + +定義於: [packages/form-core/src/formOptions.ts:3](https://github.com/TanStack/form/blob/main/packages/form-core/src/formOptions.ts#L3) + +## 型別參數 + +• **T** *繼承自* `Partial`\<[`FormOptions`](../interfaces/formoptions.md)\<`any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\>\> + +## 參數 + +### defaultOpts + +`T` + +## 回傳值 + +`T` diff --git a/docs/zh-hant/reference/functions/mergeform.md b/docs/zh-hant/reference/functions/mergeform.md new file mode 100644 index 000000000..3c8c09784 --- /dev/null +++ b/docs/zh-hant/reference/functions/mergeform.md @@ -0,0 +1,33 @@ +--- +source-updated-at: '2025-04-02T16:32:51.000Z' +translation-updated-at: '2025-04-25T20:49:09.473Z' +id: mergeForm +title: 函式 / mergeForm +--- + + +# 函式: mergeForm() + +```ts +function mergeForm(baseForm, state): FormApi, any, any, any, any, any, any, any, any, any> +``` + +定義於: [packages/form-core/src/mergeForm.ts:73](https://github.com/TanStack/form/blob/main/packages/form-core/src/mergeForm.ts#L73) + +## 型別參數 + +• **TFormData** + +## 參數 + +### baseForm + +[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\> + +### state + +`Partial`\<[`FormState`](../interfaces/formstate.md)\<`TFormData`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\>\> + +## 回傳值 + +[`FormApi`](../classes/formapi.md)\<`NoInfer`\<`TFormData`\>, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`, `any`\> diff --git a/docs/zh-hant/reference/index.md b/docs/zh-hant/reference/index.md new file mode 100644 index 000000000..e1ee0ac25 --- /dev/null +++ b/docs/zh-hant/reference/index.md @@ -0,0 +1,90 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:49:40.507Z' +id: '@tanstack/form-core' +title: JavaScript 參考 +--- + + +# @tanstack/form-core + +## 類別 (Classes) + +- [FieldApi](classes/fieldapi.md) +- [FormApi](classes/formapi.md) + +## 介面 (Interfaces) + +- [AnyDeepKeyAndValue](interfaces/anydeepkeyandvalue.md) +- [ArrayDeepKeyAndValue](interfaces/arraydeepkeyandvalue.md) +- [FieldApiOptions](interfaces/fieldapioptions.md) +- [FieldListeners](interfaces/fieldlisteners.md) +- [FieldOptions](interfaces/fieldoptions.md) +- [FieldValidators](interfaces/fieldvalidators.md) +- [FormListeners](interfaces/formlisteners.md) +- [FormOptions](interfaces/formoptions.md) +- [FormState](interfaces/formstate.md) +- [FormValidators](interfaces/formvalidators.md) +- [ObjectDeepKeyAndValue](interfaces/objectdeepkeyandvalue.md) +- [StandardSchemaV1Issue](interfaces/standardschemav1issue.md) +- [TupleDeepKeyAndValue](interfaces/tupledeepkeyandvalue.md) +- [UnknownDeepKeyAndValue](interfaces/unknowndeepkeyandvalue.md) + +## 型別別名 (Type Aliases) + +- [AllObjectKeys](type-aliases/allobjectkeys.md) +- [AllTupleKeys](type-aliases/alltuplekeys.md) +- [AnyFieldApi](type-aliases/anyfieldapi.md) +- [AnyFieldMeta](type-aliases/anyfieldmeta.md) +- [AnyFieldMetaBase](type-aliases/anyfieldmetabase.md) +- [AnyFieldMetaDerived](type-aliases/anyfieldmetaderived.md) +- [AnyFormApi](type-aliases/anyformapi.md) +- [AnyFormState](type-aliases/anyformstate.md) +- [ArrayAccessor](type-aliases/arrayaccessor.md) +- [BaseFormState](type-aliases/baseformstate.md) +- [DeepKeyAndValueArray](type-aliases/deepkeyandvaluearray.md) +- [DeepKeyAndValueObject](type-aliases/deepkeyandvalueobject.md) +- [DeepKeyAndValueTuple](type-aliases/deepkeyandvaluetuple.md) +- [DeepKeys](type-aliases/deepkeys.md) +- [DeepKeysAndValues](type-aliases/deepkeysandvalues.md) +- [DeepKeysAndValuesImpl](type-aliases/deepkeysandvaluesimpl.md) +- [DeepRecord](type-aliases/deeprecord.md) +- [DeepValue](type-aliases/deepvalue.md) +- [DerivedFormState](type-aliases/derivedformstate.md) +- [FieldInfo](type-aliases/fieldinfo.md) +- [FieldMeta](type-aliases/fieldmeta.md) +- [FieldMetaBase](type-aliases/fieldmetabase.md) +- [FieldMetaDerived](type-aliases/fieldmetaderived.md) +- [FieldState](type-aliases/fieldstate.md) +- [FormValidateFn](type-aliases/formvalidatefn.md) +- [FormValidationError](type-aliases/formvalidationerror.md) +- [FormValidator](type-aliases/formvalidator.md) +- [Nullable](type-aliases/nullable.md) +- [ObjectAccessor](type-aliases/objectaccessor.md) +- [ObjectValue](type-aliases/objectvalue.md) +- [StandardSchemaV1](type-aliases/standardschemav1.md) +- [TStandardSchemaValidatorIssue](type-aliases/tstandardschemavalidatorissue.md) +- [TStandardSchemaValidatorValue](type-aliases/tstandardschemavalidatorvalue.md) +- [TupleAccessor](type-aliases/tupleaccessor.md) +- [UnknownAccessor](type-aliases/unknownaccessor.md) +- [UnwrapFieldAsyncValidateOrFn](type-aliases/unwrapfieldasyncvalidateorfn.md) +- [UnwrapFieldValidateOrFn](type-aliases/unwrapfieldvalidateorfn.md) +- [UnwrapFormAsyncValidateOrFn](type-aliases/unwrapformasyncvalidateorfn.md) +- [UnwrapFormValidateOrFn](type-aliases/unwrapformvalidateorfn.md) +- [Updater](type-aliases/updater.md) +- [UpdaterFn](type-aliases/updaterfn.md) +- [ValidationError](type-aliases/validationerror.md) +- [ValidationMeta](type-aliases/validationmeta.md) +- [ValidationSource](type-aliases/validationsource.md) + +## 變數 (Variables) + +- [standardSchemaValidators](variables/standardschemavalidators.md) + +## 函式 (Functions) + +- [formOptions](functions/formoptions.md) +- [isGlobalFormValidationError](functions/isglobalformvalidationerror.md) +- [isStandardSchemaValidator](functions/isstandardschemavalidator.md) +- [mergeForm](functions/mergeform.md) +- [shallow](functions/shallow.md) diff --git a/docs/zh-hant/reference/interfaces/fieldapioptions.md b/docs/zh-hant/reference/interfaces/fieldapioptions.md new file mode 100644 index 000000000..6705df861 --- /dev/null +++ b/docs/zh-hant/reference/interfaces/fieldapioptions.md @@ -0,0 +1,195 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:50:09.855Z' +id: FieldApiOptions +title: 介面 / FieldApiOptions +--- + + +# 介面: FieldApiOptions\ + +定義於: [packages/form-core/src/FieldApi.ts:455](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L455) + +表示 FieldApi 類別所需選項的物件類型。 + +## 擴展 + +- [`FieldOptions`](fieldoptions.md)\<`TParentData`, `TName`, `TData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`\> + +## 類型參數 + +• **TParentData** + +• **TName** *繼承* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> + +• **TData** *繼承* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *繼承* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnServer** *繼承* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TParentSubmitMeta** + +## 屬性 + +### asyncAlways? + +```ts +optional asyncAlways: boolean; +``` + +定義於: [packages/form-core/src/FieldApi.ts:402](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L402) + +若為 `true`,即使同步驗證過程中出現錯誤,仍會執行非同步驗證。 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`asyncAlways`](FieldOptions.md#asyncalways) + +*** + +### asyncDebounceMs? + +```ts +optional asyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FieldApi.ts:398](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L398) + +若未傳入更特定的防抖時間,則為非同步驗證的預設防抖時間。 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`asyncDebounceMs`](FieldOptions.md#asyncdebouncems) + +*** + +### defaultMeta? + +```ts +optional defaultMeta: Partial>; +``` + +定義於: [packages/form-core/src/FieldApi.ts:421](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L421) + +欄位的預設元資料 (metadata) 物件,可選。 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`defaultMeta`](FieldOptions.md#defaultmeta) + +*** + +### defaultValue? + +```ts +optional defaultValue: NoInfer; +``` + +定義於: [packages/form-core/src/FieldApi.ts:394](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L394) + +欄位的預設值,可選。 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`defaultValue`](FieldOptions.md#defaultvalue) + +*** + +### disableErrorFlat? + +```ts +optional disableErrorFlat: boolean; +``` + +定義於: [packages/form-core/src/FieldApi.ts:449](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L449) + +禁用 `field.errors` 上的 `flat(1)` 操作。這適用於您希望保持錯誤結構不變的情況。不建議用於大多數使用場景。 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`disableErrorFlat`](FieldOptions.md#disableerrorflat) + +*** + +### form + +```ts +form: FormApi; +``` + +定義於: [packages/form-core/src/FieldApi.ts:507](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L507) + +*** + +### listeners? + +```ts +optional listeners: FieldListeners; +``` + +定義於: [packages/form-core/src/FieldApi.ts:445](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L445) + +附加到相應事件的監聽器列表 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`listeners`](FieldOptions.md#listeners) + +*** + +### name + +```ts +name: TName; +``` + +定義於: [packages/form-core/src/FieldApi.ts:390](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L390) + +欄位名稱。類型為 `DeepKeys`,以確保您的名稱是父資料集的深層鍵名。 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`name`](FieldOptions.md#name) + +*** + +### validators? + +```ts +optional validators: FieldValidators; +``` + +定義於: [packages/form-core/src/FieldApi.ts:406](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L406) + +傳遞給欄位的驗證器列表 + +#### 繼承自 + +[`FieldOptions`](fieldoptions.md).[`validators`](FieldOptions.md#validators) diff --git a/docs/zh-hant/reference/interfaces/fieldoptions.md b/docs/zh-hant/reference/interfaces/fieldoptions.md new file mode 100644 index 000000000..aa4993b38 --- /dev/null +++ b/docs/zh-hant/reference/interfaces/fieldoptions.md @@ -0,0 +1,133 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:52:22.471Z' +id: FieldOptions +title: 介面 / FieldOptions +--- +# 介面: FieldOptions\ + +定義於: [packages/form-core/src/FieldApi.ts:369](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L369) + +表示表單欄位選項的物件類型。 + +## 擴展自 + +- [`FieldApiOptions`](fieldapioptions.md) + +## 型別參數 + +• **TParentData** + +• **TName** *繼承自* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> + +• **TData** *繼承自* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 屬性 + +### asyncAlways? + +```ts +optional asyncAlways: boolean; +``` + +定義於: [packages/form-core/src/FieldApi.ts:402](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L402) + +若為 `true`,則總是執行非同步驗證,即使在同步驗證期間已產生錯誤。 + +*** + +### asyncDebounceMs? + +```ts +optional asyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FieldApi.ts:398](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L398) + +若未傳入更具體的防抖時間,則此為非同步驗證的預設防抖時間。 + +*** + +### defaultMeta? + +```ts +optional defaultMeta: Partial>; +``` + +定義於: [packages/form-core/src/FieldApi.ts:421](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L421) + +用於欄位的預設元資料選用物件。 + +*** + +### defaultValue? + +```ts +optional defaultValue: NoInfer; +``` + +定義於: [packages/form-core/src/FieldApi.ts:394](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L394) + +欄位的選用預設值。 + +*** + +### disableErrorFlat? + +```ts +optional disableErrorFlat: boolean; +``` + +定義於: [packages/form-core/src/FieldApi.ts:449](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L449) + +停用 `field.errors` 上的 `flat(1)` 操作。這在您希望保持錯誤結構不變時很有用。不建議用於大多數情況。 + +*** + +### listeners? + +```ts +optional listeners: FieldListeners; +``` + +定義於: [packages/form-core/src/FieldApi.ts:445](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L445) + +附加到相應事件的監聽器列表 + +*** + +### name + +```ts +name: TName; +``` + +定義於: [packages/form-core/src/FieldApi.ts:390](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L390) + +欄位名稱。型別為 `DeepKeys` 以確保您的名稱是父資料集的深層鍵。 + +*** + +### validators? + +```ts +optional validators: FieldValidators; +``` + +定義於: [packages/form-core/src/FieldApi.ts:406](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L406) + +傳遞給欄位的驗證器列表 diff --git a/docs/zh-hant/reference/interfaces/fieldvalidators.md b/docs/zh-hant/reference/interfaces/fieldvalidators.md new file mode 100644 index 000000000..69ef6e630 --- /dev/null +++ b/docs/zh-hant/reference/interfaces/fieldvalidators.md @@ -0,0 +1,203 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:52:57.035Z' +id: FieldValidators +title: 介面 / FieldValidators +--- +# 介面: FieldValidators\ + +定義於: [packages/form-core/src/FieldApi.ts:272](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L272) + +## 型別參數 + +• **TParentData** + +• **TName** *extends* [`DeepKeys`](../type-aliases/deepkeys.md)\<`TParentData`\> + +• **TData** *extends* [`DeepValue`](../type-aliases/deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *extends* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *extends* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +## 屬性 + +### onBlur? + +```ts +optional onBlur: TOnBlur; +``` + +定義於: [packages/form-core/src/FieldApi.ts:321](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L321) + +一個可選函式,會在輸入框的 blur 事件時執行。 + +#### 範例 + +```ts +z.string().min(1) +``` + +*** + +### onBlurAsync? + +```ts +optional onBlurAsync: TOnBlurAsync; +``` + +定義於: [packages/form-core/src/FieldApi.ts:327](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L327) + +一個可選屬性,類似 `onBlur` 但為非同步驗證。 + +#### 範例 + +```ts +z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) +``` + +*** + +### onBlurAsyncDebounceMs? + +```ts +optional onBlurAsyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FieldApi.ts:334](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L334) + +一個可選數字,表示 `onBlurAsync` 在執行前應等待的時間 + +如果設為大於 0 的數字,將會以毫秒為單位對非同步驗證事件進行防抖處理 + +*** + +### onBlurListenTo? + +```ts +optional onBlurListenTo: DeepKeys[]; +``` + +定義於: [packages/form-core/src/FieldApi.ts:338](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L338) + +一個可選欄位名稱列表,當這些欄位的值變更時,會觸發此欄位的 `onBlur` 和 `onBlurAsync` 事件 + +*** + +### onChange? + +```ts +optional onChange: TOnChange; +``` + +定義於: [packages/form-core/src/FieldApi.ts:299](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L299) + +一個可選函式,會在輸入框的 change 事件時執行。 + +#### 範例 + +```ts +z.string().min(1) +``` + +*** + +### onChangeAsync? + +```ts +optional onChangeAsync: TOnChangeAsync; +``` + +定義於: [packages/form-core/src/FieldApi.ts:305](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L305) + +一個可選屬性,類似 `onChange` 但為非同步驗證 + +#### 範例 + +```ts +z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) +``` + +*** + +### onChangeAsyncDebounceMs? + +```ts +optional onChangeAsyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FieldApi.ts:311](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L311) + +一個可選數字,表示 `onChangeAsync` 在執行前應等待的時間 + +如果設為大於 0 的數字,將會以毫秒為單位對非同步驗證事件進行防抖處理 + +*** + +### onChangeListenTo? + +```ts +optional onChangeListenTo: DeepKeys[]; +``` + +定義於: [packages/form-core/src/FieldApi.ts:315](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L315) + +一個可選欄位名稱列表,當這些欄位的值變更時,會觸發此欄位的 `onChange` 和 `onChangeAsync` 事件 + +*** + +### onMount? + +```ts +optional onMount: TOnMount; +``` + +定義於: [packages/form-core/src/FieldApi.ts:293](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L293) + +一個可選函式,會在輸入框的 mount 事件時執行。 + +*** + +### onSubmit? + +```ts +optional onSubmit: TOnSubmit; +``` + +定義於: [packages/form-core/src/FieldApi.ts:344](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L344) + +一個可選函式,會在表單的 submit 事件時執行。 + +#### 範例 + +```ts +z.string().min(1) +``` + +*** + +### onSubmitAsync? + +```ts +optional onSubmitAsync: TOnSubmitAsync; +``` + +定義於: [packages/form-core/src/FieldApi.ts:350](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L350) + +一個可選屬性,類似 `onSubmit` 但為非同步驗證。 + +#### 範例 + +```ts +z.string().refine(async (val) => val.length > 3, { message: 'Testing 123' }) +``` diff --git a/docs/zh-hant/reference/interfaces/formoptions.md b/docs/zh-hant/reference/interfaces/formoptions.md new file mode 100644 index 000000000..560e2b901 --- /dev/null +++ b/docs/zh-hant/reference/interfaces/formoptions.md @@ -0,0 +1,199 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:52:58.829Z' +id: FormOptions +title: 介面 / FormOptions +--- +# 介面: FormOptions\ + +定義於: [packages/form-core/src/FormApi.ts:319](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L319) + +代表表單選項的物件。 + +## 型別參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TSubmitMeta** = `never` + +## 屬性 + +### asyncAlways? + +```ts +optional asyncAlways: boolean; +``` + +定義於: [packages/form-core/src/FormApi.ts:354](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L354) + +若為 true,即使同步驗證已產生錯誤,仍會執行非同步驗證。預設為 undefined。 + +*** + +### asyncDebounceMs? + +```ts +optional asyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FormApi.ts:358](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L358) + +可選的毫秒數,用於在觸發非同步動作前引入延遲。 + +*** + +### canSubmitWhenInvalid? + +```ts +optional canSubmitWhenInvalid: boolean; +``` + +定義於: [packages/form-core/src/FormApi.ts:362](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L362) + +若為 true,允許表單在無效狀態下提交,即 canSubmit 將保持為 true,無論驗證錯誤為何。預設為 undefined。 + +*** + +### defaultState? + +```ts +optional defaultState: Partial>; +``` + +定義於: [packages/form-core/src/FormApi.ts:338](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L338) + +表單的預設狀態。 + +*** + +### defaultValues? + +```ts +optional defaultValues: TFormData; +``` + +定義於: [packages/form-core/src/FormApi.ts:334](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L334) + +設定表單的初始值。 + +*** + +### listeners? + +```ts +optional listeners: FormListeners; +``` + +定義於: [packages/form-core/src/FormApi.ts:385](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L385) + +表單層級的監聽器 + +*** + +### onSubmit()? + +```ts +optional onSubmit: (props) => any; +``` + +定義於: [packages/form-core/src/FormApi.ts:401](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L401) + +當表單提交時呼叫的函式,定義使用者提交有效表單後應執行的動作,回傳 `any` 或 Promise `Promise` + +#### 參數 + +##### props + +###### formApi + +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +###### meta + +`TSubmitMeta` + +###### value + +`TFormData` + +#### 回傳值 + +`any` + +*** + +### onSubmitInvalid()? + +```ts +optional onSubmitInvalid: (props) => void; +``` + +定義於: [packages/form-core/src/FormApi.ts:420](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L420) + +指定當使用者嘗試提交無效表單時應執行的動作。 + +#### 參數 + +##### props + +###### formApi + +[`FormApi`](../classes/formapi.md)\<`TFormData`, `TOnMount`, `TOnChange`, `TOnChangeAsync`, `TOnBlur`, `TOnBlurAsync`, `TOnSubmit`, `TOnSubmitAsync`, `TOnServer`, `TSubmitMeta`\> + +###### value + +`TFormData` + +#### 回傳值 + +`void` + +*** + +### onSubmitMeta? + +```ts +optional onSubmitMeta: TSubmitMeta; +``` + +定義於: [packages/form-core/src/FormApi.ts:380](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L380) + +onSubmitMeta,從 handleSubmit 處理函式傳遞給 onSubmit 函式 props 的資料 + +*** + +### transform? + +```ts +optional transform: FormTransform, NoInfer, NoInfer, NoInfer, NoInfer, NoInfer, NoInfer, NoInfer, NoInfer, NoInfer>; +``` + +定義於: [packages/form-core/src/FormApi.ts:435](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L435) + +*** + +### validators? + +```ts +optional validators: FormValidators; +``` + +定義於: [packages/form-core/src/FormApi.ts:366](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L366) + +傳遞給表單的驗證器列表 diff --git a/docs/zh-hant/reference/interfaces/formvalidators.md b/docs/zh-hant/reference/interfaces/formvalidators.md new file mode 100644 index 000000000..5abcc2860 --- /dev/null +++ b/docs/zh-hant/reference/interfaces/formvalidators.md @@ -0,0 +1,131 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:52:38.470Z' +id: FormValidators +title: 介面 / FormValidators +--- +# 介面: FormValidators\ + +定義於: [packages/form-core/src/FormApi.ts:156](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L156) + +## 型別參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +## 屬性 + +### onBlur? + +```ts +optional onBlur: TOnBlur; +``` + +定義於: [packages/form-core/src/FormApi.ts:185](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L185) + +選擇性函式,當欄位失去焦點時驗證表單資料,回傳 `FormValidationError` + +*** + +### onBlurAsync? + +```ts +optional onBlurAsync: TOnBlurAsync; +``` + +定義於: [packages/form-core/src/FormApi.ts:189](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L189) + +選擇性的 onBlur 非同步驗證方法,當欄位失去焦點時回傳 `FormValidationError` 或 `Promise` + +*** + +### onBlurAsyncDebounceMs? + +```ts +optional onBlurAsyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FormApi.ts:193](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L193) + +預設的毫秒數,若設定為大於 0 的數字,會以此毫秒數延遲非同步驗證事件。 + +*** + +### onChange? + +```ts +optional onChange: TOnChange; +``` + +定義於: [packages/form-core/src/FormApi.ts:173](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L173) + +選擇性函式,當值變更時檢查資料的有效性 + +*** + +### onChangeAsync? + +```ts +optional onChangeAsync: TOnChangeAsync; +``` + +定義於: [packages/form-core/src/FormApi.ts:177](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L177) + +選擇性的 onChange 非同步對應方法,適用於更複雜的驗證邏輯,可能包含伺服器請求。 + +*** + +### onChangeAsyncDebounceMs? + +```ts +optional onChangeAsyncDebounceMs: number; +``` + +定義於: [packages/form-core/src/FormApi.ts:181](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L181) + +預設的毫秒數,若設定為大於 0 的數字,會以此毫秒數延遲非同步驗證事件。 + +*** + +### onMount? + +```ts +optional onMount: TOnMount; +``` + +定義於: [packages/form-core/src/FormApi.ts:169](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L169) + +選擇性函式,在元件掛載時立即觸發。 + +*** + +### onSubmit? + +```ts +optional onSubmit: TOnSubmit; +``` + +定義於: [packages/form-core/src/FormApi.ts:194](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L194) + +*** + +### onSubmitAsync? + +```ts +optional onSubmitAsync: TOnSubmitAsync; +``` + +定義於: [packages/form-core/src/FormApi.ts:195](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L195) diff --git a/docs/zh-hant/reference/type-aliases/baseformstate.md b/docs/zh-hant/reference/type-aliases/baseformstate.md new file mode 100644 index 000000000..5115a9d4f --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/baseformstate.md @@ -0,0 +1,129 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:52:36.068Z' +id: BaseFormState +title: 類型 / BaseFormState +--- +# 類型別名: BaseFormState\ + +```ts +type BaseFormState = object; +``` + +定義於: [packages/form-core/src/FormApi.ts:496](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L496) + +代表表單當前狀態的物件。 + +## 類型參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +## 類型宣告 + +### \_force\_re\_eval? + +```ts +optional _force_re_eval: boolean; +``` + +@private, 用於在選項變更時強制重新評估表單狀態 + +### errorMap + +```ts +errorMap: FormValidationErrorMap, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormValidateOrFn, UnwrapFormAsyncValidateOrFn, UnwrapFormAsyncValidateOrFn>; +``` + +表單本身的錯誤映射。 + +### fieldMetaBase + +```ts +fieldMetaBase: Record, AnyFieldMetaBase>; +``` + +表單中每個欄位的元資料記錄,不包含衍生屬性,如 `errors` 等 + +### isSubmitSuccessful + +```ts +isSubmitSuccessful: boolean; +``` + +表示最後一次提交是否成功的布林值。 + +### isSubmitted + +```ts +isSubmitted: boolean; +``` + +表示 `onSubmit` 函式是否已成功完成的布林值。 + +每次新的提交嘗試時會重置為 `false`。 + +注意: 您可以使用 isSubmitting 來檢查表單當前是否正在提交。 + +### isSubmitting + +```ts +isSubmitting: boolean; +``` + +表示在呼叫 `handleSubmit` 後表單當前是否正在提交的布林值。 + +在以下情況之一完成時會重置為 `false`: +- 驗證步驟返回錯誤。 +- `onSubmit` 函式已完成。 + +注意: 如果您在 `onSubmit` 函式中執行非同步操作,請確保等待它們完成,以確保 `isSubmitting` 僅在非同步操作完成時設為 `false`。 + +這對於在提交期間顯示載入指示器或禁用表單輸入非常有用。 + +### isValidating + +```ts +isValidating: boolean; +``` + +表示表單或其任何欄位當前是否正在驗證的布林值。 + +### submissionAttempts + +```ts +submissionAttempts: number; +``` + +追蹤提交嘗試次數的計數器。 + +### validationMetaMap + +```ts +validationMetaMap: Record; +``` + +用於追蹤表單中驗證邏輯的內部機制。 + +### values + +```ts +values: TFormData; +``` + +表單欄位的當前值。 diff --git a/docs/zh-hant/reference/type-aliases/deepkeys.md b/docs/zh-hant/reference/type-aliases/deepkeys.md new file mode 100644 index 000000000..3b845cd9b --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/deepkeys.md @@ -0,0 +1,21 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:52:04.099Z' +id: DeepKeys +title: 類型 / DeepKeys +--- + + +# 類型別名: DeepKeys\ + +```ts +type DeepKeys = unknown extends T ? string : DeepKeysAndValues["key"]; +``` + +定義於: [packages/form-core/src/util-types.ts:157](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L157) + +取得物件或陣列的鍵名 (key),包含深層嵌套的鍵名。 + +## 類型參數 + +• **T** diff --git a/docs/zh-hant/reference/type-aliases/deepvalue.md b/docs/zh-hant/reference/type-aliases/deepvalue.md new file mode 100644 index 000000000..84959aacd --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/deepvalue.md @@ -0,0 +1,23 @@ +--- +source-updated-at: '2025-04-19T08:22:21.000Z' +translation-updated-at: '2025-04-25T20:52:04.937Z' +id: DeepValue +title: 類型 / DeepValue +--- + + +# 類型別名:DeepValue\ + +```ts +type DeepValue = unknown extends TValue ? TValue : TAccessor extends DeepKeys ? DeepRecord[TAccessor] : never; +``` + +定義於:[packages/form-core/src/util-types.ts:164](https://github.com/TanStack/form/blob/main/packages/form-core/src/util-types.ts#L164) + +推斷物件或陣列中深層嵌套屬性的類型。 + +## 類型參數 + +• **TValue** + +• **TAccessor** diff --git a/docs/zh-hant/reference/type-aliases/derivedformstate.md b/docs/zh-hant/reference/type-aliases/derivedformstate.md new file mode 100644 index 000000000..82fdfa770 --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/derivedformstate.md @@ -0,0 +1,139 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:52:33.990Z' +id: DerivedFormState +title: 類型 / DerivedFormState +--- +# 型別別名:DerivedFormState\ + +```ts +type DerivedFormState = object; +``` + +定義於:[packages/form-core/src/FormApi.ts:571](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L571) + +## 型別參數 + +• **TFormData** + +• **TOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TFormData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +• **TOnServer** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TFormData`\> + +## 型別宣告 + +### canSubmit + +```ts +canSubmit: boolean; +``` + +表示表單是否可根據當前狀態提交的布林值。 + +### errors + +```ts +errors: ( + | UnwrapFormValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormValidateOrFn + | UnwrapFormAsyncValidateOrFn + | UnwrapFormAsyncValidateOrFn)[]; +``` + +表單本身的錯誤陣列。 + +### fieldMeta + +```ts +fieldMeta: Record, AnyFieldMeta>; +``` + +表單中每個欄位的欄位元資料記錄。 + +### isBlurred + +```ts +isBlurred: boolean; +``` + +表示表單中是否有任何欄位已失去焦點的布林值。 + +### isDirty + +```ts +isDirty: boolean; +``` + +表示表單中是否有任何欄位的值已被使用者修改的布林值。若使用者修改了至少一個欄位則為 `true`。與 `isPristine` 相反。 + +### isFieldsValid + +```ts +isFieldsValid: boolean; +``` + +表示表單中所有欄位是否有效的布林值。 + +### isFieldsValidating + +```ts +isFieldsValidating: boolean; +``` + +表示表單中是否有任何欄位正在驗證的布林值。 + +### isFormValid + +```ts +isFormValid: boolean; +``` + +表示表單是否有效的布林值。 + +### isFormValidating + +```ts +isFormValidating: boolean; +``` + +表示表單是否正在驗證的布林值。 + +### isPristine + +```ts +isPristine: boolean; +``` + +表示表單中所有欄位的值是否未被使用者修改的布林值。若使用者未修改任何欄位則為 `true`。與 `isDirty` 相反。 + +### isTouched + +```ts +isTouched: boolean; +``` + +表示表單中是否有任何欄位已被觸碰的布林值。 + +### isValid + +```ts +isValid: boolean; +``` + +表示表單及其所有欄位是否有效的布林值。 diff --git a/docs/zh-hant/reference/type-aliases/fieldmeta.md b/docs/zh-hant/reference/type-aliases/fieldmeta.md new file mode 100644 index 000000000..41c61d1f9 --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/fieldmeta.md @@ -0,0 +1,51 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:52:36.667Z' +id: FieldMeta +title: 類型 / FieldMeta +--- +# 類型別名: FieldMeta\ + +```ts +type FieldMeta = FieldMetaBase & FieldMetaDerived; +``` + +定義於: [packages/form-core/src/FieldApi.ts:680](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L680) + +一個物件類型,表示表單中欄位的元數據 (metadata)。 + +## 類型參數 + +• **TParentData** + +• **TName** *繼承自* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TData** *繼承自* [`DeepValue`](deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> diff --git a/docs/zh-hant/reference/type-aliases/fieldstate.md b/docs/zh-hant/reference/type-aliases/fieldstate.md new file mode 100644 index 000000000..909918e51 --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/fieldstate.md @@ -0,0 +1,69 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:52:34.687Z' +id: FieldState +title: 類型 / FieldState +--- +# 類型別名: FieldState\ + +```ts +type FieldState = object; +``` + +定義於: [packages/form-core/src/FieldApi.ts:766](https://github.com/TanStack/form/blob/main/packages/form-core/src/FieldApi.ts#L766) + +表示欄位狀態的物件類型。 + +## 類型參數 + +• **TParentData** + +• **TName** *繼承自* [`DeepKeys`](deepkeys.md)\<`TParentData`\> + +• **TData** *繼承自* [`DeepValue`](deepvalue.md)\<`TParentData`, `TName`\> + +• **TOnMount** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChange** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnChangeAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlur** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnBlurAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmit** *繼承自* `undefined` \| `FieldValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TOnSubmitAsync** *繼承自* `undefined` \| `FieldAsyncValidateOrFn`\<`TParentData`, `TName`, `TData`\> + +• **TFormOnMount** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChange** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnChangeAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnBlur** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnBlurAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmit** *繼承自* `undefined` \| `FormValidateOrFn`\<`TParentData`\> + +• **TFormOnSubmitAsync** *繼承自* `undefined` \| `FormAsyncValidateOrFn`\<`TParentData`\> + +## 類型宣告 + +### meta + +```ts +meta: FieldMeta; +``` + +欄位當前的元數據 (metadata)。 + +### value + +```ts +value: TData; +``` + +欄位當前的值。 diff --git a/docs/zh-hant/reference/type-aliases/updater.md b/docs/zh-hant/reference/type-aliases/updater.md new file mode 100644 index 000000000..968b87a57 --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/updater.md @@ -0,0 +1,21 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:53:08.519Z' +id: Updater +title: 類型 / Updater +--- + + +# 類型別名:更新器函式〈TInput, TOutput〉 + +```ts +type Updater = TOutput | UpdaterFn; +``` + +定義於:[packages/form-core/src/utils.ts:12](https://github.com/TanStack/form/blob/main/packages/form-core/src/utils.ts#L12) + +## 類型參數 + +• **TInput** + +• **TOutput** = `TInput` diff --git a/docs/zh-hant/reference/type-aliases/updaterfn.md b/docs/zh-hant/reference/type-aliases/updaterfn.md new file mode 100644 index 000000000..6f483d31f --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/updaterfn.md @@ -0,0 +1,31 @@ +--- +source-updated-at: '2025-04-20T06:54:03.000Z' +translation-updated-at: '2025-04-25T20:53:17.206Z' +id: UpdaterFn +title: 類型 / UpdaterFn +--- + + +# 類型別名:UpdaterFn()\ + +```ts +type UpdaterFn = (input) => TOutput; +``` + +定義於:[packages/form-core/src/utils.ts:10](https://github.com/TanStack/form/blob/main/packages/form-core/src/utils.ts#L10) + +## 類型參數 + +• **TInput** + +• **TOutput** = `TInput` + +## 參數 + +### input + +`TInput` + +## 回傳值 + +`TOutput` diff --git a/docs/zh-hant/reference/type-aliases/validationerror.md b/docs/zh-hant/reference/type-aliases/validationerror.md new file mode 100644 index 000000000..f63378fe9 --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/validationerror.md @@ -0,0 +1,15 @@ +--- +source-updated-at: '2025-02-22T01:19:17.000Z' +translation-updated-at: '2025-04-25T20:53:23.775Z' +id: ValidationError +title: 類型 / ValidationError +--- + + +# 類型別名:ValidationError + +```ts +type ValidationError = unknown; +``` + +定義於:[packages/form-core/src/types.ts:3](https://github.com/TanStack/form/blob/main/packages/form-core/src/types.ts#L3) diff --git a/docs/zh-hant/reference/type-aliases/validationmeta.md b/docs/zh-hant/reference/type-aliases/validationmeta.md new file mode 100644 index 000000000..5cf95d3a2 --- /dev/null +++ b/docs/zh-hant/reference/type-aliases/validationmeta.md @@ -0,0 +1,27 @@ +--- +source-updated-at: '2025-04-25T12:58:29.000Z' +translation-updated-at: '2025-04-25T20:53:32.639Z' +id: ValidationMeta +title: 類型 / ValidationMeta +--- + + +# 類型別名:ValidationMeta + +```ts +type ValidationMeta = object; +``` + +定義於:[packages/form-core/src/FormApi.ts:452](https://github.com/TanStack/form/blob/main/packages/form-core/src/FormApi.ts#L452) + +表示欄位驗證元資料的物件,不建議公開使用。 + +## 類型宣告 + +### lastAbortController + +```ts +lastAbortController: AbortController; +``` + +儲存在記憶體中的中止控制器 (AbortController),用於取消先前的非同步驗證嘗試。 diff --git a/docs/zh-hant/typescript.md b/docs/zh-hant/typescript.md new file mode 100644 index 000000000..58d05ca72 --- /dev/null +++ b/docs/zh-hant/typescript.md @@ -0,0 +1,15 @@ +--- +source-updated-at: '2025-03-01T06:06:46.000Z' +translation-updated-at: '2025-04-25T20:31:16.928Z' +id: typescript +title: TypeScript +--- +TanStack Form 完全使用 **TypeScript** 編寫,具備最高品質的泛型 (generics)、約束 (constraints) 和介面 (interfaces),確保函式庫與您的專案能達到最高程度的型別安全 (type-safe)! + +注意事項: + +- 您的 `tsconfig.json` 中必須設定 `strict: true` 才能充分發揮 TanStack Form 的型別功能 +- 目前型別系統要求使用 TypeScript v5.4 或更高版本 +- 本儲存庫中的型別變更視為**非破壞性變更 (non-breaking)**,通常會以**修補版本 (patch)** 的語意化版本 (semver) 形式發布(否則每個型別增強都會變成主版本號更新!) +- **強烈建議您將 react-form 套件版本鎖定在特定的修補版本,並在升級時預期型別可能在任意版本間被修正或升級** +- TanStack Form 的非型別相關公開 API 仍嚴格遵循語意化版本規範。 From 124939978d75b62970e3f8fd98fc453d845eb681 Mon Sep 17 00:00:00 2001 From: "yanqi.zong" Date: Mon, 28 Apr 2025 09:50:30 -0700 Subject: [PATCH 2/2] docs: format docs --- docs/zh-hans/comparison.md | 35 ++++++++++--------- .../framework/angular/guides/arrays.md | 1 + .../angular/guides/basic-concepts.md | 1 + .../framework/angular/guides/validation.md | 1 + docs/zh-hans/framework/angular/quick-start.md | 1 + docs/zh-hans/framework/lit/guides/arrays.md | 1 + .../framework/lit/guides/basic-concepts.md | 1 + docs/zh-hans/framework/lit/quick-start.md | 1 + .../react/community/balastrong-tutorial.md | 1 + docs/zh-hans/framework/react/guides/arrays.md | 1 + .../react/guides/async-initial-values.md | 1 + .../framework/react/guides/basic-concepts.md | 1 + .../framework/react/guides/custom-errors.md | 8 ++--- .../framework/react/guides/debugging.md | 1 + .../react/guides/form-composition.md | 1 + .../framework/react/guides/linked-fields.md | 1 + .../framework/react/guides/listeners.md | 1 + .../framework/react/guides/react-native.md | 1 + .../framework/react/guides/reactivity.md | 1 + docs/zh-hans/framework/react/guides/ssr.md | 7 ++-- .../react/guides/submission-handling.md | 1 + .../framework/react/guides/ui-libraries.md | 1 + .../framework/react/guides/validation.md | 1 + docs/zh-hans/framework/react/quick-start.md | 4 +-- docs/zh-hans/framework/solid/guides/arrays.md | 1 + .../solid/guides/async-initial-values.md | 1 + .../framework/solid/guides/basic-concepts.md | 3 +- .../framework/solid/guides/linked-fields.md | 1 + .../framework/solid/guides/validation.md | 1 + docs/zh-hans/framework/solid/quick-start.md | 1 + docs/zh-hans/framework/vue/guides/arrays.md | 1 + .../vue/guides/async-initial-values.md | 1 + .../framework/vue/guides/basic-concepts.md | 1 + .../framework/vue/guides/linked-fields.md | 1 + .../framework/vue/guides/validation.md | 1 + docs/zh-hans/framework/vue/quick-start.md | 1 + docs/zh-hans/installation.md | 1 + docs/zh-hans/overview.md | 1 + docs/zh-hans/philosophy.md | 1 + docs/zh-hans/typescript.md | 1 + docs/zh-hant/comparison.md | 35 ++++++++++--------- docs/zh-hant/config.json | 2 +- .../framework/angular/guides/validation.md | 1 + docs/zh-hant/framework/angular/quick-start.md | 1 + docs/zh-hant/framework/lit/guides/arrays.md | 1 + .../framework/lit/guides/basic-concepts.md | 1 + docs/zh-hant/framework/lit/quick-start.md | 1 + .../react/community/balastrong-tutorial.md | 1 + docs/zh-hant/framework/react/guides/arrays.md | 1 + .../react/guides/async-initial-values.md | 1 + .../framework/react/guides/basic-concepts.md | 1 + .../framework/react/guides/custom-errors.md | 1 + .../framework/react/guides/debugging.md | 1 + .../react/guides/form-composition.md | 1 + .../framework/react/guides/linked-fields.md | 1 + .../framework/react/guides/listeners.md | 1 + .../framework/react/guides/react-native.md | 1 + .../framework/react/guides/reactivity.md | 1 + docs/zh-hant/framework/react/guides/ssr.md | 1 + .../react/guides/submission-handling.md | 1 + .../framework/react/guides/ui-libraries.md | 1 + .../framework/react/guides/validation.md | 1 + docs/zh-hant/framework/react/quick-start.md | 1 + docs/zh-hant/framework/solid/guides/arrays.md | 1 + .../solid/guides/async-initial-values.md | 1 + .../framework/solid/guides/basic-concepts.md | 1 + .../framework/solid/guides/linked-fields.md | 1 + .../framework/solid/guides/validation.md | 1 + docs/zh-hant/framework/solid/quick-start.md | 1 + .../zh-hant/framework/svelte/guides/arrays.md | 1 + .../svelte/guides/async-initial-values.md | 1 + .../framework/svelte/guides/basic-concepts.md | 1 + .../framework/svelte/guides/linked-fields.md | 1 + .../framework/svelte/guides/validation.md | 1 + docs/zh-hant/framework/vue/guides/arrays.md | 1 + .../vue/guides/async-initial-values.md | 1 + .../framework/vue/guides/basic-concepts.md | 1 + .../framework/vue/guides/linked-fields.md | 1 + .../framework/vue/guides/validation.md | 1 + docs/zh-hant/framework/vue/quick-start.md | 1 + docs/zh-hant/installation.md | 1 + docs/zh-hant/overview.md | 1 + docs/zh-hant/philosophy.md | 3 ++ docs/zh-hant/typescript.md | 1 + 84 files changed, 127 insertions(+), 46 deletions(-) diff --git a/docs/zh-hans/comparison.md b/docs/zh-hans/comparison.md index 95d01342d..bebb584ea 100644 --- a/docs/zh-hans/comparison.md +++ b/docs/zh-hans/comparison.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:03.149Z' id: comparison title: 对比 --- + > ⚠️ 本对比表格正在完善中,部分信息可能不够准确。如果您使用过其中任一库并认为信息可以改进,欢迎通过页面底部的 "Edit this page on Github" 链接提交修改建议(需附说明或证据)。 功能/能力说明: @@ -13,23 +14,23 @@ title: 对比 - 🔶 支持且有文档,但需要用户自行编写额外代码 - 🛑 官方不支持或无文档 -| 功能 | TanStack Form | Formik | Redux Form | React Hook Form | Final Form | -| -------------------------------------------------- | -------------------------------------------- | ------------------------------ | -------------------------------------- | ------------------------------------------------ | -------------------------------------- | -| GitHub 仓库/星标数 | [![][stars-tanstack-form]][gh-tanstack-form] | [![][stars-formik]][gh-formik] | [![][stars-redux-form]][gh-redux-form] | [![][stars-react-hook-form]][gh-react-hook-form] | [![][stars-final-form]][gh-final-form] | -| 支持框架 | React, Vue, Angular, Solid, Lit | React | React | React | React, Vue, Angular, Solid, Vanilla JS | -| 打包体积 | [![][bp-tanstack-form]][bpl-tanstack-form] | [![][bp-formik]][bpl-formik] | [![][bp-redux-form]][bpl-redux-form] | [![][bp-react-hook-form]][bpl-react-hook-form] | [![][bp-final-form]][bpl-final-form] | -| 一流的 TypeScript 支持 | ✅ | ❓ | ❓ | ✅ | ✅ | -| 完整的 TypeScript 类型推断(包含深层字段) | ✅ | ❓ | ❓ | ✅ | 🛑 | -| 无头 UI 组件 (Headless UI) | ✅ | ❓ | ❓ | ✅ | ❓ | -| 框架无关性 | ✅ | ❓ | ❓ | 🛑 | ✅ | -| 细粒度响应式 | ✅ | ❓ | ❓ | ❓ | ✅ | -| 嵌套对象/数组字段 | ✅ | ✅ | ❓ | ✅\*(1) | ✅ | -| 异步验证 | ✅ | ✅ | ❓ | ✅ | ✅ | -| 内置异步验证防抖 | ✅ | ❓ | ❓ | ❓ | ❓ | -| 基于模式的验证 (Schema-based Validation) | ✅ | ✅ | ❓ | ✅ | ❓ | -| 官方开发者工具 | 🛑\*(2) | 🛑 | ✅\*(3) | ✅ | ❓ | -| 服务端渲染集成 (SSR integrations) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 | -| React 编译器支持 (React Compiler support) | ✅ | ❓ | ❓ | 🛑 | ❓ | +| 功能 | TanStack Form | Formik | Redux Form | React Hook Form | Final Form | +| ------------------------------------------ | -------------------------------------------- | ------------------------------ | -------------------------------------- | ------------------------------------------------ | -------------------------------------- | +| GitHub 仓库/星标数 | [![][stars-tanstack-form]][gh-tanstack-form] | [![][stars-formik]][gh-formik] | [![][stars-redux-form]][gh-redux-form] | [![][stars-react-hook-form]][gh-react-hook-form] | [![][stars-final-form]][gh-final-form] | +| 支持框架 | React, Vue, Angular, Solid, Lit | React | React | React | React, Vue, Angular, Solid, Vanilla JS | +| 打包体积 | [![][bp-tanstack-form]][bpl-tanstack-form] | [![][bp-formik]][bpl-formik] | [![][bp-redux-form]][bpl-redux-form] | [![][bp-react-hook-form]][bpl-react-hook-form] | [![][bp-final-form]][bpl-final-form] | +| 一流的 TypeScript 支持 | ✅ | ❓ | ❓ | ✅ | ✅ | +| 完整的 TypeScript 类型推断(包含深层字段) | ✅ | ❓ | ❓ | ✅ | 🛑 | +| 无头 UI 组件 (Headless UI) | ✅ | ❓ | ❓ | ✅ | ❓ | +| 框架无关性 | ✅ | ❓ | ❓ | 🛑 | ✅ | +| 细粒度响应式 | ✅ | ❓ | ❓ | ❓ | ✅ | +| 嵌套对象/数组字段 | ✅ | ✅ | ❓ | ✅\*(1) | ✅ | +| 异步验证 | ✅ | ✅ | ❓ | ✅ | ✅ | +| 内置异步验证防抖 | ✅ | ❓ | ❓ | ❓ | ❓ | +| 基于模式的验证 (Schema-based Validation) | ✅ | ✅ | ❓ | ✅ | ❓ | +| 官方开发者工具 | 🛑\*(2) | 🛑 | ✅\*(3) | ✅ | ❓ | +| 服务端渲染集成 (SSR integrations) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 | +| React 编译器支持 (React Compiler support) | ✅ | ❓ | ❓ | 🛑 | ❓ | \*(1) 对于嵌套数组,使用 TypeScript 时 react-hook-form 要求[通过字段名进行类型转换](https://react-hook-form.com/docs/usefieldarray) diff --git a/docs/zh-hans/framework/angular/guides/arrays.md b/docs/zh-hans/framework/angular/guides/arrays.md index fa4779538..22c9e555b 100644 --- a/docs/zh-hans/framework/angular/guides/arrays.md +++ b/docs/zh-hans/framework/angular/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:10:43.653Z' id: arrays title: 数组 --- + TanStack Form 支持将数组作为表单值使用,包括数组中的子对象值。 ## 基本用法 diff --git a/docs/zh-hans/framework/angular/guides/basic-concepts.md b/docs/zh-hans/framework/angular/guides/basic-concepts.md index bbf9c80ac..924f3bb14 100644 --- a/docs/zh-hans/framework/angular/guides/basic-concepts.md +++ b/docs/zh-hans/framework/angular/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:17.959Z' id: basic-concepts title: 基本概念 --- + 本页面介绍了 `@tanstack/angular-form` 库中使用的基本概念和术语。熟悉这些概念将帮助您更好地理解和使用该库。 ## 表单实例 (Form Instance) diff --git a/docs/zh-hans/framework/angular/guides/validation.md b/docs/zh-hans/framework/angular/guides/validation.md index 43ce921b7..ff859c78e 100644 --- a/docs/zh-hans/framework/angular/guides/validation.md +++ b/docs/zh-hans/framework/angular/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:12:19.741Z' id: form-validation title: 表单验证 --- + 表单与字段验证 (Form and Field Validation) TanStack Form 的核心功能之一是验证机制。TanStack Form 提供了高度可定制的验证方式: diff --git a/docs/zh-hans/framework/angular/quick-start.md b/docs/zh-hans/framework/angular/quick-start.md index 6238aeecf..54a255420 100644 --- a/docs/zh-hans/framework/angular/quick-start.md +++ b/docs/zh-hans/framework/angular/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:25.901Z' id: quick-start title: 快速开始 --- + ## 快速入门 使用 TanStack Form 的最基本步骤是创建一个表单并添加字段。请注意,以下示例尚未包含任何验证或错误处理功能。 diff --git a/docs/zh-hans/framework/lit/guides/arrays.md b/docs/zh-hans/framework/lit/guides/arrays.md index 980a7ed6e..24a00c505 100644 --- a/docs/zh-hans/framework/lit/guides/arrays.md +++ b/docs/zh-hans/framework/lit/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:36.599Z' id: arrays title: 数组 --- + TanStack Form 支持将数组作为表单值使用,包括数组内的子对象值。 ## 基本用法 diff --git a/docs/zh-hans/framework/lit/guides/basic-concepts.md b/docs/zh-hans/framework/lit/guides/basic-concepts.md index 4c8cb4082..120221c20 100644 --- a/docs/zh-hans/framework/lit/guides/basic-concepts.md +++ b/docs/zh-hans/framework/lit/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:24.303Z' id: basic-concepts title: 基本概念 --- + 本页介绍 `@tanstack/lit-form` 库中使用的基本概念和术语。熟悉这些概念将帮助您更好地理解并运用该库及其与 Lit 的配合使用。 ## 表单选项 (Form Options) diff --git a/docs/zh-hans/framework/lit/quick-start.md b/docs/zh-hans/framework/lit/quick-start.md index 600b69985..f25b53e60 100644 --- a/docs/zh-hans/framework/lit/quick-start.md +++ b/docs/zh-hans/framework/lit/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:31.027Z' id: quick-start title: 快速开始 --- + ## 快速入门 开始使用 TanStack Form 的最低要求是创建一个 `TanstackFormController`,如下所示,我们使用 `Employee` 接口作为测试表单的数据结构: diff --git a/docs/zh-hans/framework/react/community/balastrong-tutorial.md b/docs/zh-hans/framework/react/community/balastrong-tutorial.md index 9e9549532..c045ec953 100644 --- a/docs/zh-hans/framework/react/community/balastrong-tutorial.md +++ b/docs/zh-hans/framework/react/community/balastrong-tutorial.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:14:38.417Z' id: balastrong-tutorial title: Balastrong的教程 --- + TanStack Form 维护者 [Balastrong](https://bsky.app/profile/leonardomontini.dev) 制作了一系列视频教程,展示了该库最核心的功能。通过这些循序渐进的指南,您将深入了解如何使用 TanStack Form 构建功能,并获取实用技巧。 [观看完整播放列表](https://www.youtube.com/playlist?list=PLOQjd5dsGSxInTKUWTxyqSKwZCjDIUs0Y) diff --git a/docs/zh-hans/framework/react/guides/arrays.md b/docs/zh-hans/framework/react/guides/arrays.md index 25f5bf6da..fa0c2b0ba 100644 --- a/docs/zh-hans/framework/react/guides/arrays.md +++ b/docs/zh-hans/framework/react/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:53.544Z' id: arrays title: 数组 --- + TanStack Form 支持将数组作为表单值,包括数组内的子对象值。 ## 基础用法 diff --git a/docs/zh-hans/framework/react/guides/async-initial-values.md b/docs/zh-hans/framework/react/guides/async-initial-values.md index a6075ff09..a91ec2adb 100644 --- a/docs/zh-hans/framework/react/guides/async-initial-values.md +++ b/docs/zh-hans/framework/react/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:42.790Z' id: async-initial-values title: 异步初始值 --- + ## 异步初始值 假设您需要从 API 获取数据并将其作为表单的初始值。 diff --git a/docs/zh-hans/framework/react/guides/basic-concepts.md b/docs/zh-hans/framework/react/guides/basic-concepts.md index 35d7c5059..d198b5ad5 100644 --- a/docs/zh-hans/framework/react/guides/basic-concepts.md +++ b/docs/zh-hans/framework/react/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:47.860Z' id: basic-concepts title: 基本概念 --- + 本页面介绍 `@tanstack/react-form` 库中使用的基本概念和术语。熟悉这些概念将帮助您更好地理解和使用该库。 ## 表单选项 (Form Options) diff --git a/docs/zh-hans/framework/react/guides/custom-errors.md b/docs/zh-hans/framework/react/guides/custom-errors.md index 0a45713ed..0794ef818 100644 --- a/docs/zh-hans/framework/react/guides/custom-errors.md +++ b/docs/zh-hans/framework/react/guides/custom-errors.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:56.557Z' id: custom-errors title: 自定义错误 --- + TanStack Form 为验证器返回的错误值类型提供了完全的灵活性。字符串错误是最常见且易于处理的类型,但该库允许您从验证器中返回任何类型的值。 作为通用规则,任何真值(truthy value)都会被视作错误,并将表单或字段标记为无效;而假值(falsy values,如 `false`、`undefined`、`null` 等)则表示没有错误,表单或字段有效。 @@ -32,8 +33,7 @@ const form = useForm({ onChange: ({ value }) => { return { fields: { - username: - value.username.length < 3 ? '用户名过短' : undefined, + username: value.username.length < 3 ? '用户名过短' : undefined, email: !value.email.includes('@') ? '无效的邮箱地址' : undefined, }, } @@ -73,9 +73,7 @@ const form = useForm({ { /* TypeScript 会根据验证器推断错误类型为数字 */ } -;
- 您还需要 {field.state.meta.errors[0]} 年才符合资格 -
+;
您还需要 {field.state.meta.errors[0]} 年才符合资格
``` ### 布尔类型 diff --git a/docs/zh-hans/framework/react/guides/debugging.md b/docs/zh-hans/framework/react/guides/debugging.md index 32ce7940f..ca235f77a 100644 --- a/docs/zh-hans/framework/react/guides/debugging.md +++ b/docs/zh-hans/framework/react/guides/debugging.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:26.089Z' id: debugging title: 调试 --- + 以下是您可能在控制台中遇到的常见错误列表及其解决方法。 ## 将非受控输入更改为受控输入 diff --git a/docs/zh-hans/framework/react/guides/form-composition.md b/docs/zh-hans/framework/react/guides/form-composition.md index 1f52b476e..42389d563 100644 --- a/docs/zh-hans/framework/react/guides/form-composition.md +++ b/docs/zh-hans/framework/react/guides/form-composition.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:10:42.863Z' id: form-composition title: 表单组合 --- + # 表单组合 (Form Composition) 对 TanStack Form 的一个常见批评是其开箱即用的冗长性。虽然这对于教育目的可能有用——有助于强化对 API 的理解——但在生产用例中并不理想。 diff --git a/docs/zh-hans/framework/react/guides/linked-fields.md b/docs/zh-hans/framework/react/guides/linked-fields.md index 19448b911..56d1cc1be 100644 --- a/docs/zh-hans/framework/react/guides/linked-fields.md +++ b/docs/zh-hans/framework/react/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:50.083Z' id: linked-fields title: 关联字段 --- + ## 联动两个表单字段 在某些场景下,您可能需要将两个字段进行联动:当其中一个字段的值发生变化时,另一个字段需要重新验证。一个典型用例是同时存在 `password` 和 `confirm_password` 字段的情况,此时需要确保当 `password` 字段值不匹配时,`confirm_password` 字段能立即显示错误——无论哪个字段触发了值的变化。 diff --git a/docs/zh-hans/framework/react/guides/listeners.md b/docs/zh-hans/framework/react/guides/listeners.md index 6dc1df64c..2ae3a0f0a 100644 --- a/docs/zh-hans/framework/react/guides/listeners.md +++ b/docs/zh-hans/framework/react/guides/listeners.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:58.594Z' id: listeners title: 监听器 --- + ## 事件触发器的副作用处理 当您需要"影响"或"响应"某些触发行为时,可以使用监听器 (listener) API。例如,如果您作为开发者希望在某个字段变化时重置另一个表单字段,就应该使用监听器 API。 diff --git a/docs/zh-hans/framework/react/guides/react-native.md b/docs/zh-hans/framework/react/guides/react-native.md index 2d7af0821..1f159039d 100644 --- a/docs/zh-hans/framework/react/guides/react-native.md +++ b/docs/zh-hans/framework/react/guides/react-native.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:09.238Z' id: react-native title: React Native --- + ## 动机 大多数 Web 框架并未提供全面的表单处理方案,迫使开发者要么自行实现定制方案,要么依赖功能有限的库。这往往导致一致性缺失、性能低下以及开发时间增加。TanStack Form 旨在通过提供一套强大易用的全功能表单管理方案来解决这些问题。 diff --git a/docs/zh-hans/framework/react/guides/reactivity.md b/docs/zh-hans/framework/react/guides/reactivity.md index 1cb09b26b..b98faba5f 100644 --- a/docs/zh-hans/framework/react/guides/reactivity.md +++ b/docs/zh-hans/framework/react/guides/reactivity.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:53.631Z' id: reactivity title: 响应式 --- + Tanstack Form 在与表单交互时不会触发重新渲染。因此您可能会发现直接使用表单或字段状态值无法获得预期效果。 如需访问响应式值,您需要通过以下两种方法之一进行订阅:`useStore` 钩子或 `form.Subscribe` 组件。 diff --git a/docs/zh-hans/framework/react/guides/ssr.md b/docs/zh-hans/framework/react/guides/ssr.md index c2a03193e..6f9ddea35 100644 --- a/docs/zh-hans/framework/react/guides/ssr.md +++ b/docs/zh-hans/framework/react/guides/ssr.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:11.947Z' id: ssr title: SSR/TanStack Start/Next.js --- + TanStack Form 开箱即支持 React,兼容 服务端渲染 (SSR) 并保持框架无关性。但需要根据您选择的元框架进行特定配置。 目前我们支持以下元框架: @@ -323,13 +324,13 @@ export const ClientComp = () => { 此处我们结合使用了 [React 的 useActionState 钩子](https://playfulprogramming.com/posts/what-is-use-action-state-and-form-status) 和 TanStack Form 的 useTransform 钩子来合并服务端动作返回的状态与表单状态。 > 如果在 Next.js 应用中遇到以下错误: -> +> > ```typescript > x 您正在导入需要 useState 的组件。此 React 钩子仅在客户端组件中有效。解决方法是在文件(或其父级)中添加 "use client" 指令 > ``` -> +> > 这是因为您没有从 `@tanstack/react-form/nextjs` 导入服务端代码。请确保根据运行环境导入正确的模块。 -> +> > [这是 Next.js 的已知限制](https://github.com/phryneas/rehackt)。其他元框架通常不会出现此问题。 ## 在 Remix 中使用 TanStack Form diff --git a/docs/zh-hans/framework/react/guides/submission-handling.md b/docs/zh-hans/framework/react/guides/submission-handling.md index e8c30ec83..a9ad01c60 100644 --- a/docs/zh-hans/framework/react/guides/submission-handling.md +++ b/docs/zh-hans/framework/react/guides/submission-handling.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:04.203Z' id: submission-handling title: 提交处理 --- + 在需要处理多种表单提交类型的场景下(例如,一个表单同时包含导航至子表单的按钮和执行标准提交的按钮),可以利用 `onSubmitMeta` 属性和 `handleSubmit` 函数的重载机制。 ## 基础用法 diff --git a/docs/zh-hans/framework/react/guides/ui-libraries.md b/docs/zh-hans/framework/react/guides/ui-libraries.md index 138972088..8e4317f76 100644 --- a/docs/zh-hans/framework/react/guides/ui-libraries.md +++ b/docs/zh-hans/framework/react/guides/ui-libraries.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:36.714Z' id: ui-libraries title: UI库集成 --- + ## 在 UI 库中使用 TanStack Form TanStack Form 是一个无头 (headless) 库,为您提供完全的样式定制灵活性。它能与多种 UI 库兼容,包括 `Tailwind`、`Material UI`、`Mantine` 甚至原生 CSS。 diff --git a/docs/zh-hans/framework/react/guides/validation.md b/docs/zh-hans/framework/react/guides/validation.md index 661fdd8be..861bbc904 100644 --- a/docs/zh-hans/framework/react/guides/validation.md +++ b/docs/zh-hans/framework/react/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:10:47.393Z' id: form-validation title: 表单验证 --- + 表单与字段验证 (Form and Field Validation) TanStack Form 的核心功能之一是验证机制。它提供了高度可定制的验证方式: diff --git a/docs/zh-hans/framework/react/quick-start.md b/docs/zh-hans/framework/react/quick-start.md index a6682d856..686c7d430 100644 --- a/docs/zh-hans/framework/react/quick-start.md +++ b/docs/zh-hans/framework/react/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:52.516Z' id: quick-start title: 快速开始 --- + TanStack Form 与你以往使用的大多数表单库不同。它专为大规模生产环境设计,注重类型安全、性能与组合能力,旨在提供无与伦比的开发者体验。 为此,我们制定了[库的使用哲学](/form/latest/docs/philosophy),更重视可扩展性和长期开发者体验,而非简短可分享的代码片段。 @@ -109,8 +110,7 @@ const PeoplePage = () => { name="age" validators={{ // 可选择表单级或字段级验证器 - onChange: ({ value }) => - value > 13 ? undefined : '必须年满 13 岁', + onChange: ({ value }) => (value > 13 ? undefined : '必须年满 13 岁'), }} children={(field) => ( <> diff --git a/docs/zh-hans/framework/solid/guides/arrays.md b/docs/zh-hans/framework/solid/guides/arrays.md index 480b35329..6e6a4368f 100644 --- a/docs/zh-hans/framework/solid/guides/arrays.md +++ b/docs/zh-hans/framework/solid/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:14.180Z' id: arrays title: 数组 --- + TanStack Form 支持将数组作为表单值使用,包括数组内的子对象值。 ## 基本用法 diff --git a/docs/zh-hans/framework/solid/guides/async-initial-values.md b/docs/zh-hans/framework/solid/guides/async-initial-values.md index b974b9b74..581e86352 100644 --- a/docs/zh-hans/framework/solid/guides/async-initial-values.md +++ b/docs/zh-hans/framework/solid/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:00.234Z' id: async-initial-values title: 异步初始值 --- + 假设您需要从 API 获取数据并将其作为表单的初始值使用。 虽然这个问题表面看起来简单,但背后存在一些您可能尚未考虑到的隐藏复杂性。 diff --git a/docs/zh-hans/framework/solid/guides/basic-concepts.md b/docs/zh-hans/framework/solid/guides/basic-concepts.md index 4196bbed6..7be6aff1f 100644 --- a/docs/zh-hans/framework/solid/guides/basic-concepts.md +++ b/docs/zh-hans/framework/solid/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:10:54.326Z' id: basic-concepts title: 基本概念 --- + 本页面介绍了 `@tanstack/solid-form` 库中使用的基本概念和术语。熟悉这些概念将帮助您更好地理解和使用该库。 ## 表单选项 (Form Options) @@ -150,7 +151,7 @@ import { z } from 'zod' await new Promise((resolve) => setTimeout(resolve, 1000)) return !value.includes('error') }, - { message: '名中不能包含"error"' } + { message: '名中不能包含"error"' }, ), }} /> diff --git a/docs/zh-hans/framework/solid/guides/linked-fields.md b/docs/zh-hans/framework/solid/guides/linked-fields.md index 24f925dcf..500e28769 100644 --- a/docs/zh-hans/framework/solid/guides/linked-fields.md +++ b/docs/zh-hans/framework/solid/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:07.786Z' id: linked-fields title: 关联字段 --- + ## 联动两个表单字段 在某些场景下,您可能需要将两个表单字段关联起来:当其中一个字段的值发生变化时,触发另一个字段的验证逻辑。 diff --git a/docs/zh-hans/framework/solid/guides/validation.md b/docs/zh-hans/framework/solid/guides/validation.md index 9f67068df..a264b6253 100644 --- a/docs/zh-hans/framework/solid/guides/validation.md +++ b/docs/zh-hans/framework/solid/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:12:06.653Z' id: form-validation title: 表单验证 --- + 表单与字段验证 (Form and Field Validation) TanStack Form 的核心功能之一是高度可定制的验证机制: diff --git a/docs/zh-hans/framework/solid/quick-start.md b/docs/zh-hans/framework/solid/quick-start.md index c77d99773..681e03fbf 100644 --- a/docs/zh-hans/framework/solid/quick-start.md +++ b/docs/zh-hans/framework/solid/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:24.395Z' id: quick-start title: 快速开始 --- + ## 快速入门 开始使用 TanStack Form 的最低要求是创建一个表单并添加一个字段。请注意,这个示例尚未包含任何验证或错误处理功能。 diff --git a/docs/zh-hans/framework/vue/guides/arrays.md b/docs/zh-hans/framework/vue/guides/arrays.md index f3bf722b4..da4c840d5 100644 --- a/docs/zh-hans/framework/vue/guides/arrays.md +++ b/docs/zh-hans/framework/vue/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:10:04.251Z' id: arrays title: 数组 --- + TanStack Form 支持将数组作为表单值使用,包括数组内的子对象值。 ## 基本用法 diff --git a/docs/zh-hans/framework/vue/guides/async-initial-values.md b/docs/zh-hans/framework/vue/guides/async-initial-values.md index b3bd5c1d3..b5e89a7ee 100644 --- a/docs/zh-hans/framework/vue/guides/async-initial-values.md +++ b/docs/zh-hans/framework/vue/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:29.672Z' id: async-initial-values title: 异步初始值 --- + 假设您需要从 API 获取数据并将其作为表单的初始值。 虽然这个问题表面看起来简单,但背后隐藏着您可能尚未考虑的复杂性。 diff --git a/docs/zh-hans/framework/vue/guides/basic-concepts.md b/docs/zh-hans/framework/vue/guides/basic-concepts.md index de9427fce..f739c6133 100644 --- a/docs/zh-hans/framework/vue/guides/basic-concepts.md +++ b/docs/zh-hans/framework/vue/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:10:42.406Z' id: basic-concepts title: 基本概念 --- + 本页介绍 `@tanstack/vue-form` 库中使用的基本概念和术语。熟悉这些概念将帮助您更好地理解和使用该库。 ## 表单配置项 (Form Options) diff --git a/docs/zh-hans/framework/vue/guides/linked-fields.md b/docs/zh-hans/framework/vue/guides/linked-fields.md index 4c0bbb79e..517157c6d 100644 --- a/docs/zh-hans/framework/vue/guides/linked-fields.md +++ b/docs/zh-hans/framework/vue/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:09:57.125Z' id: linked-fields title: 关联字段 --- + ## 联动两个表单字段 在某些场景下,您可能需要将两个字段进行联动验证:当其中一个字段的值发生变化时,另一个字段需要重新验证。一个典型用例是同时存在 `password` 和 `confirm_password` 字段的情况,此时需要确保当 `password` 字段的值不匹配时,`confirm_password` 字段能立即显示错误——无论哪个字段触发了值的变化。 diff --git a/docs/zh-hans/framework/vue/guides/validation.md b/docs/zh-hans/framework/vue/guides/validation.md index b7f03d8bd..f50c41e09 100644 --- a/docs/zh-hans/framework/vue/guides/validation.md +++ b/docs/zh-hans/framework/vue/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:11:25.487Z' id: form-validation title: 表单验证 --- + TanStack Form 的核心功能之一是验证 (validation) 概念。TanStack Form 使验证具有高度可定制性: - 您可以控制何时执行验证(在值变更时、输入时、失焦时、提交时...) diff --git a/docs/zh-hans/framework/vue/quick-start.md b/docs/zh-hans/framework/vue/quick-start.md index 3eaba94c6..8edc72bac 100644 --- a/docs/zh-hans/framework/vue/quick-start.md +++ b/docs/zh-hans/framework/vue/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:22.956Z' id: quick-start title: 快速开始 --- + ## 快速开始 使用 TanStack Form 的最低要求是创建一个表单并添加一个字段。请注意,当前示例尚未包含任何验证或错误处理功能。 diff --git a/docs/zh-hans/installation.md b/docs/zh-hans/installation.md index 7301a94b3..5fb4c3de7 100644 --- a/docs/zh-hans/installation.md +++ b/docs/zh-hans/installation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:27.039Z' id: installation title: 安装 --- + ## 安装 TanStack Form 兼容多种前端框架,包括 React、Vue 和 Solid。要结合您选用的框架使用 TanStack Form,请通过您偏好的包管理器安装对应的适配器: diff --git a/docs/zh-hans/overview.md b/docs/zh-hans/overview.md index 29ea87b22..c49c585fe 100644 --- a/docs/zh-hans/overview.md +++ b/docs/zh-hans/overview.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:52.717Z' id: overview title: 概述 --- + TanStack Form 是处理 Web 应用中表单的终极解决方案,提供了一种强大而灵活的表单管理方法。它具备一流的 TypeScript 支持、无头 UI 组件 (headless UI components) 和框架无关的设计 (framework-agnostic design),简化了表单处理流程,并确保在不同前端框架中都能获得无缝体验。 ## 动机 diff --git a/docs/zh-hans/philosophy.md b/docs/zh-hans/philosophy.md index a4f901bfb..9d4f34feb 100644 --- a/docs/zh-hans/philosophy.md +++ b/docs/zh-hans/philosophy.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:37.807Z' id: philosophy title: 设计理念 --- + 每个成熟的项目都应具备指导其开发的核心哲学。缺乏核心理念的开发会陷入无休止的决策困境,最终导致 API 设计薄弱。 本文档阐述了驱动 TanStack Form 开发与功能设计的核心原则。 diff --git a/docs/zh-hans/typescript.md b/docs/zh-hans/typescript.md index 7b6dc4d20..d21d9649b 100644 --- a/docs/zh-hans/typescript.md +++ b/docs/zh-hans/typescript.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-12T04:08:19.788Z' id: typescript title: TypeScript --- + TanStack Form 完全采用 **TypeScript** 编写,具备最高质量的泛型、约束和接口设计,确保该库与您的项目实现最大程度的类型安全! 注意事项: diff --git a/docs/zh-hant/comparison.md b/docs/zh-hant/comparison.md index de5b9929b..d50d45d48 100644 --- a/docs/zh-hant/comparison.md +++ b/docs/zh-hant/comparison.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:55.484Z' id: comparison title: 比較 --- + > ⚠️ 此比較表格正在建構中,內容尚未完全準確。如果您使用過其中任何函式庫並認為資訊可以改進,歡迎透過頁面底部的「Edit this page on Github」連結提出修改建議(需附上說明或佐證資料)。 功能/能力對照說明: @@ -13,23 +14,23 @@ title: 比較 - 🔶 支援且有文件說明,但需要使用者自行撰寫額外程式碼來實作 - 🛑 官方不支援或無相關文件 -| 功能 | TanStack Form | Formik | Redux Form | React Hook Form | Final Form | -| ---------------------------------------------- | -------------------------------------------- | ------------------------------ | -------------------------------------- | ------------------------------------------------ | -------------------------------------- | -| GitHub 儲存庫/星數 | [![][stars-tanstack-form]][gh-tanstack-form] | [![][stars-formik]][gh-formik] | [![][stars-redux-form]][gh-redux-form] | [![][stars-react-hook-form]][gh-react-hook-form] | [![][stars-final-form]][gh-final-form] | -| 支援的框架 | React, Vue, Angular, Solid, Lit | React | React | React | React, Vue, Angular, Solid, Vanilla JS | -| 套件大小 | [![][bp-tanstack-form]][bpl-tanstack-form] | [![][bp-formik]][bpl-formik] | [![][bp-redux-form]][bpl-redux-form] | [![][bp-react-hook-form]][bpl-react-hook-form] | [![][bp-final-form]][bpl-final-form] | -| 完善的 TypeScript 支援 | ✅ | ❓ | ❓ | ✅ | ✅ | -| 完整的 TypeScript 型別推論(包含深層欄位) | ✅ | ❓ | ❓ | ✅ | 🛑 | -| 無頭 UI 元件 (Headless UI) | ✅ | ❓ | ❓ | ✅ | ❓ | -| 框架無關性 | ✅ | ❓ | ❓ | 🛑 | ✅ | -| 細粒度響應式更新 | ✅ | ❓ | ❓ | ❓ | ✅ | -| 支援巢狀物件/陣列欄位 | ✅ | ✅ | ❓ | ✅\*(1) | ✅ | -| 非同步驗證 | ✅ | ✅ | ❓ | ✅ | ✅ | -| 內建非同步驗證防抖動 | ✅ | ❓ | ❓ | ❓ | ❓ | -| 基於結構描述的驗證 (Schema-based Validation) | ✅ | ✅ | ❓ | ✅ | ❓ | -| 官方開發者工具 | 🛑\*(2) | 🛑 | ✅\*(3) | ✅ | ❓ | -| 伺服器渲染整合 (SSR) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 | -| React 編譯器支援 | ✅ | ❓ | ❓ | 🛑 | ❓ | +| 功能 | TanStack Form | Formik | Redux Form | React Hook Form | Final Form | +| -------------------------------------------- | -------------------------------------------- | ------------------------------ | -------------------------------------- | ------------------------------------------------ | -------------------------------------- | +| GitHub 儲存庫/星數 | [![][stars-tanstack-form]][gh-tanstack-form] | [![][stars-formik]][gh-formik] | [![][stars-redux-form]][gh-redux-form] | [![][stars-react-hook-form]][gh-react-hook-form] | [![][stars-final-form]][gh-final-form] | +| 支援的框架 | React, Vue, Angular, Solid, Lit | React | React | React | React, Vue, Angular, Solid, Vanilla JS | +| 套件大小 | [![][bp-tanstack-form]][bpl-tanstack-form] | [![][bp-formik]][bpl-formik] | [![][bp-redux-form]][bpl-redux-form] | [![][bp-react-hook-form]][bpl-react-hook-form] | [![][bp-final-form]][bpl-final-form] | +| 完善的 TypeScript 支援 | ✅ | ❓ | ❓ | ✅ | ✅ | +| 完整的 TypeScript 型別推論(包含深層欄位) | ✅ | ❓ | ❓ | ✅ | 🛑 | +| 無頭 UI 元件 (Headless UI) | ✅ | ❓ | ❓ | ✅ | ❓ | +| 框架無關性 | ✅ | ❓ | ❓ | 🛑 | ✅ | +| 細粒度響應式更新 | ✅ | ❓ | ❓ | ❓ | ✅ | +| 支援巢狀物件/陣列欄位 | ✅ | ✅ | ❓ | ✅\*(1) | ✅ | +| 非同步驗證 | ✅ | ✅ | ❓ | ✅ | ✅ | +| 內建非同步驗證防抖動 | ✅ | ❓ | ❓ | ❓ | ❓ | +| 基於結構描述的驗證 (Schema-based Validation) | ✅ | ✅ | ❓ | ✅ | ❓ | +| 官方開發者工具 | 🛑\*(2) | 🛑 | ✅\*(3) | ✅ | ❓ | +| 伺服器渲染整合 (SSR) | ✅ | 🛑 | 🛑 | 🛑 | 🛑 | +| React 編譯器支援 | ✅ | ❓ | ❓ | 🛑 | ❓ | \*(1) 對於巢狀陣列,若使用 TypeScript,react-hook-form 要求您[需透過欄位名稱轉換欄位陣列](https://react-hook-form.com/docs/usefieldarray) diff --git a/docs/zh-hant/config.json b/docs/zh-hant/config.json index 5632a7a2e..550f33c16 100644 --- a/docs/zh-hant/config.json +++ b/docs/zh-hant/config.json @@ -609,4 +609,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/docs/zh-hant/framework/angular/guides/validation.md b/docs/zh-hant/framework/angular/guides/validation.md index ce14376fe..d96bb33af 100644 --- a/docs/zh-hant/framework/angular/guides/validation.md +++ b/docs/zh-hant/framework/angular/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:24.792Z' id: form-validation title: 表單驗證 --- + TanStack Form 的核心功能之一就是驗證 (validation) 概念。TanStack Form 讓驗證變得高度可自訂: - 您可以控制何時執行驗證(變更時、輸入時、失焦時、提交時...) diff --git a/docs/zh-hant/framework/angular/quick-start.md b/docs/zh-hant/framework/angular/quick-start.md index c2ffd4203..6b7bdc372 100644 --- a/docs/zh-hant/framework/angular/quick-start.md +++ b/docs/zh-hant/framework/angular/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:42.999Z' id: quick-start title: 快速開始 --- + ## 快速開始 使用 TanStack Form 最基本的入門步驟是建立一個表單並添加欄位。請注意,這個範例尚未包含任何驗證或錯誤處理功能...(目前僅展示基礎用法) diff --git a/docs/zh-hant/framework/lit/guides/arrays.md b/docs/zh-hant/framework/lit/guides/arrays.md index e63fc272c..2f795c38c 100644 --- a/docs/zh-hant/framework/lit/guides/arrays.md +++ b/docs/zh-hant/framework/lit/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:51.581Z' id: arrays title: 陣列 --- + TanStack Form 支援將陣列 (array) 作為表單值使用,包含陣列中的子物件值。 ## 基本用法 diff --git a/docs/zh-hant/framework/lit/guides/basic-concepts.md b/docs/zh-hant/framework/lit/guides/basic-concepts.md index d69ae3290..1b220fc38 100644 --- a/docs/zh-hant/framework/lit/guides/basic-concepts.md +++ b/docs/zh-hant/framework/lit/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:50.231Z' id: basic-concepts title: 基本概念 --- + 本頁介紹 `@tanstack/lit-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更好地理解並運用該函式庫及其與 Lit 的整合方式。 ## 表單選項 (Form Options) diff --git a/docs/zh-hant/framework/lit/quick-start.md b/docs/zh-hant/framework/lit/quick-start.md index d9c044c16..5c084e7f3 100644 --- a/docs/zh-hant/framework/lit/quick-start.md +++ b/docs/zh-hant/framework/lit/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:47.922Z' id: quick-start title: 快速開始 --- + ## 快速開始 使用 TanStack Form 的最低要求是建立一個 `TanstackFormController`,如下所示,並使用 `Employee` 介面作為測試表單的結構: diff --git a/docs/zh-hant/framework/react/community/balastrong-tutorial.md b/docs/zh-hant/framework/react/community/balastrong-tutorial.md index 4dd3271ec..961e850fe 100644 --- a/docs/zh-hant/framework/react/community/balastrong-tutorial.md +++ b/docs/zh-hant/framework/react/community/balastrong-tutorial.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:55:12.761Z' id: balastrong-tutorial title: Balastrong 教學 --- + TanStack Form 的維護者 [Balastrong](https://bsky.app/profile/leonardomontini.dev) 製作了一系列影片教學,展示該函式庫最核心的功能。您將找到逐步指南,深入了解如何使用 TanStack Form 建構功能,並獲得一些實用技巧與訣竅。 [觀看完整播放清單](https://www.youtube.com/playlist?list=PLOQjd5dsGSxInTKUWTxyqSKwZCjDIUs0Y) diff --git a/docs/zh-hant/framework/react/guides/arrays.md b/docs/zh-hant/framework/react/guides/arrays.md index 6bcbc9778..6739fff82 100644 --- a/docs/zh-hant/framework/react/guides/arrays.md +++ b/docs/zh-hant/framework/react/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:38.845Z' id: arrays title: 陣列 --- + TanStack Form 支援將陣列 (array) 作為表單值使用,包括陣列中的子物件值。 ## 基本用法 diff --git a/docs/zh-hant/framework/react/guides/async-initial-values.md b/docs/zh-hant/framework/react/guides/async-initial-values.md index a6f848031..d6f08c4d4 100644 --- a/docs/zh-hant/framework/react/guides/async-initial-values.md +++ b/docs/zh-hant/framework/react/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:29.078Z' id: async-initial-values title: 非同步初始值 --- + 假設您想從 API 獲取一些資料,並將其作為表單的初始值使用。 雖然這個問題表面上看起來很簡單,但背後可能隱藏著您尚未考慮到的複雜性。 diff --git a/docs/zh-hant/framework/react/guides/basic-concepts.md b/docs/zh-hant/framework/react/guides/basic-concepts.md index 976179597..8e6389cce 100644 --- a/docs/zh-hant/framework/react/guides/basic-concepts.md +++ b/docs/zh-hant/framework/react/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:31.771Z' id: basic-concepts title: 基本概念 --- + 本頁介紹 `@tanstack/react-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更有效地理解並運用此函式庫。 ## 表單選項 (Form Options) diff --git a/docs/zh-hant/framework/react/guides/custom-errors.md b/docs/zh-hant/framework/react/guides/custom-errors.md index 3b8351a32..dfc40767b 100644 --- a/docs/zh-hant/framework/react/guides/custom-errors.md +++ b/docs/zh-hant/framework/react/guides/custom-errors.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:34:22.749Z' id: custom-errors title: 自訂錯誤 --- + TanStack Form 提供了完整的靈活性,讓您可以從驗證器返回任何類型的錯誤值。字串錯誤是最常見且易於處理的,但該函式庫允許您從驗證器返回任何類型的值。 一般情況下,任何真值 (truthy value) 都會被視為錯誤,並將表單或欄位標記為無效;而假值 (falsy value)(`false`、`undefined`、`null` 等)則表示沒有錯誤,表單或欄位是有效的。 diff --git a/docs/zh-hant/framework/react/guides/debugging.md b/docs/zh-hant/framework/react/guides/debugging.md index 5402b5da7..b358c62be 100644 --- a/docs/zh-hant/framework/react/guides/debugging.md +++ b/docs/zh-hant/framework/react/guides/debugging.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:39:21.215Z' id: debugging title: 除錯 --- + 以下是您可能會在控制台中看到的常見錯誤列表及解決方法。 ## 將非受控輸入變更為受控輸入 diff --git a/docs/zh-hant/framework/react/guides/form-composition.md b/docs/zh-hant/framework/react/guides/form-composition.md index 979b59613..c84c9caaf 100644 --- a/docs/zh-hant/framework/react/guides/form-composition.md +++ b/docs/zh-hant/framework/react/guides/form-composition.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:36:29.116Z' id: form-composition title: 表單組合 --- + # 表單組合 (Form Composition) 對 TanStack Form 的一個常見批評是其開箱即用的冗長性。雖然這對於教育目的可能有用 — 幫助強化對 API 的理解 — 但在生產環境中使用並不理想。 diff --git a/docs/zh-hant/framework/react/guides/linked-fields.md b/docs/zh-hant/framework/react/guides/linked-fields.md index d040cfc72..9ebf1cc14 100644 --- a/docs/zh-hant/framework/react/guides/linked-fields.md +++ b/docs/zh-hant/framework/react/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:34.857Z' id: linked-fields title: 關聯欄位 --- + ## 連結兩個表單欄位 您可能會遇到需要將兩個欄位連結在一起的情況:當一個欄位驗證失敗時,另一個欄位的值已發生變化。 diff --git a/docs/zh-hant/framework/react/guides/listeners.md b/docs/zh-hant/framework/react/guides/listeners.md index 64ed55fe8..afd3c3da0 100644 --- a/docs/zh-hant/framework/react/guides/listeners.md +++ b/docs/zh-hant/framework/react/guides/listeners.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:46.836Z' id: listeners title: 監聽器 --- + ## 事件觸發的副作用 (Side effects) 當您需要「影響」或「回應」觸發事件時,可以使用監聽器 API (listener API)。舉例來說,如果您作為開發者,想要在某個欄位變更時重置另一個表單欄位,就可以使用監聽器 API。 diff --git a/docs/zh-hant/framework/react/guides/react-native.md b/docs/zh-hant/framework/react/guides/react-native.md index ac519ff4f..8f33ae476 100644 --- a/docs/zh-hant/framework/react/guides/react-native.md +++ b/docs/zh-hant/framework/react/guides/react-native.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:36:39.479Z' id: react-native title: React Native --- + ## 與 React Native 的搭配使用 TanStack Form 採用無頭設計 (headless),應該能夠直接支援 React Native 而無需任何額外設定。 diff --git a/docs/zh-hant/framework/react/guides/reactivity.md b/docs/zh-hant/framework/react/guides/reactivity.md index 04db5265e..323434034 100644 --- a/docs/zh-hant/framework/react/guides/reactivity.md +++ b/docs/zh-hant/framework/react/guides/reactivity.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:36.696Z' id: reactivity title: 響應式 --- + Tanstack Form 在與表單互動時不會觸發重新渲染 (re-renders)。因此,您可能會發現自己試圖使用表單或欄位狀態值卻無法成功。 如果您想存取響應式 (reactive) 值,您需要使用以下兩種方法之一來訂閱它們:`useStore` 或 `form.Subscribe` 元件。 diff --git a/docs/zh-hant/framework/react/guides/ssr.md b/docs/zh-hant/framework/react/guides/ssr.md index d776bade7..5a11ec512 100644 --- a/docs/zh-hant/framework/react/guides/ssr.md +++ b/docs/zh-hant/framework/react/guides/ssr.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:39:00.310Z' id: ssr title: 伺服器渲染 (SSR)/TanStack Start/Next.js --- + TanStack Form 預設即與 React 相容,支援 `SSR` 且為框架無關 (framework-agnostic)。但根據您選擇的框架,仍需進行特定配置。 目前我們支援以下元框架 (meta-frameworks): diff --git a/docs/zh-hant/framework/react/guides/submission-handling.md b/docs/zh-hant/framework/react/guides/submission-handling.md index 2c034b884..c3a390d3a 100644 --- a/docs/zh-hant/framework/react/guides/submission-handling.md +++ b/docs/zh-hant/framework/react/guides/submission-handling.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:27.381Z' id: submission-handling title: 提交處理 --- + 在需要處理多種表單提交類型的情境下,例如一個表單同時包含導向子表單的按鈕與處理標準提交的按鈕,您可以利用 `onSubmitMeta` 屬性與 `handleSubmit` 函式的多載功能來實現。 ## 基本用法 diff --git a/docs/zh-hant/framework/react/guides/ui-libraries.md b/docs/zh-hant/framework/react/guides/ui-libraries.md index f491f6283..c7e44fac6 100644 --- a/docs/zh-hant/framework/react/guides/ui-libraries.md +++ b/docs/zh-hant/framework/react/guides/ui-libraries.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:33:55.670Z' id: ui-libraries title: UI 函式庫 --- + ## 搭配 UI 函式庫使用 TanStack Form TanStack Form 是一個無頭 (headless) 函式庫,提供完整的樣式自訂彈性。它能與多種 UI 函式庫相容,包括 `Tailwind`、`Material UI`、`Mantine`,甚至是純 CSS。 diff --git a/docs/zh-hant/framework/react/guides/validation.md b/docs/zh-hant/framework/react/guides/validation.md index 2e83497a6..139d45f89 100644 --- a/docs/zh-hant/framework/react/guides/validation.md +++ b/docs/zh-hant/framework/react/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:34:32.838Z' id: form-validation title: 表單驗證 --- + ## 表單與欄位驗證 (Form and Field Validation) TanStack Form 的核心功能之一就是驗證機制。TanStack Form 讓驗證功能高度可自訂: diff --git a/docs/zh-hant/framework/react/quick-start.md b/docs/zh-hant/framework/react/quick-start.md index c7bb8dce0..39fc9b655 100644 --- a/docs/zh-hant/framework/react/quick-start.md +++ b/docs/zh-hant/framework/react/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:32:32.369Z' id: quick-start title: 快速開始 --- + TanStack Form 與您過去使用的大多數表單函式庫截然不同。它專為大規模生產環境設計,著重於類型安全、效能和組合性,提供無與倫比的開發體驗。 因此,我們圍繞函式庫的使用發展出一套[哲學理念](/form/latest/docs/philosophy),重視可擴展性和長期的開發體驗,而非簡短可分享的程式碼片段。 diff --git a/docs/zh-hant/framework/solid/guides/arrays.md b/docs/zh-hant/framework/solid/guides/arrays.md index 3cfc84582..9bd0717b4 100644 --- a/docs/zh-hant/framework/solid/guides/arrays.md +++ b/docs/zh-hant/framework/solid/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:44.864Z' id: arrays title: 陣列 --- + TanStack Form 支援將陣列 (array) 作為表單值,包含陣列中的子物件值。 ## 基本用法 diff --git a/docs/zh-hant/framework/solid/guides/async-initial-values.md b/docs/zh-hant/framework/solid/guides/async-initial-values.md index c6b41c3ed..91e4c90d6 100644 --- a/docs/zh-hant/framework/solid/guides/async-initial-values.md +++ b/docs/zh-hant/framework/solid/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:32.217Z' id: async-initial-values title: 非同步初始值 --- + 假設您想從 API 取得一些資料,並將其作為表單的初始值。 雖然這個問題表面上看起來簡單,但背後可能隱藏著您尚未考慮到的複雜性。 diff --git a/docs/zh-hant/framework/solid/guides/basic-concepts.md b/docs/zh-hant/framework/solid/guides/basic-concepts.md index 25b8964de..338543756 100644 --- a/docs/zh-hant/framework/solid/guides/basic-concepts.md +++ b/docs/zh-hant/framework/solid/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:48:36.269Z' id: basic-concepts title: 基本概念 --- + 本頁介紹 `@tanstack/solid-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更好地理解並運用此函式庫。 ## 表單選項 (Form Options) diff --git a/docs/zh-hant/framework/solid/guides/linked-fields.md b/docs/zh-hant/framework/solid/guides/linked-fields.md index 31921a34b..bbe9be0f6 100644 --- a/docs/zh-hant/framework/solid/guides/linked-fields.md +++ b/docs/zh-hant/framework/solid/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:37.261Z' id: linked-fields title: 關聯欄位 --- + 你可能會遇到需要將兩個表單欄位連結在一起的情況:當其中一個欄位需要根據另一個欄位的值變更進行驗證時。 一個常見的使用情境是當你同時有 `password` 和 `confirm_password` 欄位時, 你會希望當 `password` 的值不匹配時,`confirm_password` 能顯示錯誤; diff --git a/docs/zh-hant/framework/solid/guides/validation.md b/docs/zh-hant/framework/solid/guides/validation.md index 49e369588..ac9bc0c0a 100644 --- a/docs/zh-hant/framework/solid/guides/validation.md +++ b/docs/zh-hant/framework/solid/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:49:26.219Z' id: form-validation title: 表單驗證 --- + # 表單與欄位驗證 (Form and Field Validation) TanStack Form 的核心功能之一就是驗證機制。TanStack Form 讓驗證功能高度可自訂: diff --git a/docs/zh-hant/framework/solid/quick-start.md b/docs/zh-hant/framework/solid/quick-start.md index 795faea95..3125224ed 100644 --- a/docs/zh-hant/framework/solid/quick-start.md +++ b/docs/zh-hant/framework/solid/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:19.846Z' id: quick-start title: 快速開始 --- + ## 快速開始 使用 TanStack Form 最基本的入門步驟是建立一個表單並添加欄位。請注意,此範例尚未包含任何驗證或錯誤處理功能。 diff --git a/docs/zh-hant/framework/svelte/guides/arrays.md b/docs/zh-hant/framework/svelte/guides/arrays.md index 1f9e5eacc..c6e66e435 100644 --- a/docs/zh-hant/framework/svelte/guides/arrays.md +++ b/docs/zh-hant/framework/svelte/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:49:22.829Z' id: arrays title: 陣列 --- + TanStack Form 支援將陣列 (array) 作為表單值使用,包含陣列中的子物件值。 ## 基本用法 diff --git a/docs/zh-hant/framework/svelte/guides/async-initial-values.md b/docs/zh-hant/framework/svelte/guides/async-initial-values.md index e5eeed9c2..56f35406e 100644 --- a/docs/zh-hant/framework/svelte/guides/async-initial-values.md +++ b/docs/zh-hant/framework/svelte/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:47:47.031Z' id: async-initial-values title: 非同步初始值 --- + 假設您想從 API 取得一些資料,並將其作為表單的初始值使用。 雖然這個問題表面上看起來很簡單,但背後可能存在一些您尚未考慮到的複雜性。 diff --git a/docs/zh-hant/framework/svelte/guides/basic-concepts.md b/docs/zh-hant/framework/svelte/guides/basic-concepts.md index 611f79f6d..535989f0e 100644 --- a/docs/zh-hant/framework/svelte/guides/basic-concepts.md +++ b/docs/zh-hant/framework/svelte/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:48:34.853Z' id: basic-concepts title: 基本概念 --- + 本頁介紹 `@tanstack/svelte-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更有效地理解與使用此函式庫。 ## 表單選項 (Form Options) diff --git a/docs/zh-hant/framework/svelte/guides/linked-fields.md b/docs/zh-hant/framework/svelte/guides/linked-fields.md index b02581d2c..03e158309 100644 --- a/docs/zh-hant/framework/svelte/guides/linked-fields.md +++ b/docs/zh-hant/framework/svelte/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:49:18.805Z' id: linked-fields title: 關聯欄位 --- + ## 連結兩個表單欄位 您可能會遇到需要將兩個欄位連結在一起的情況:當其中一個欄位需要根據另一個欄位值的變動進行驗證時。 diff --git a/docs/zh-hant/framework/svelte/guides/validation.md b/docs/zh-hant/framework/svelte/guides/validation.md index a996ea9c1..7576ecc4d 100644 --- a/docs/zh-hant/framework/svelte/guides/validation.md +++ b/docs/zh-hant/framework/svelte/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:49:20.614Z' id: form-validation title: 表單驗證 --- + TanStack Form 的核心功能之一是驗證 (validation) 概念。TanStack Form 讓驗證具有高度可自訂性: - 您可以控制驗證的時機(在變更時、輸入時、失焦時、提交時...) diff --git a/docs/zh-hant/framework/vue/guides/arrays.md b/docs/zh-hant/framework/vue/guides/arrays.md index f1e451454..574f098e4 100644 --- a/docs/zh-hant/framework/vue/guides/arrays.md +++ b/docs/zh-hant/framework/vue/guides/arrays.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:44:20.324Z' id: arrays title: 陣列 --- + TanStack Form 支援將陣列 (array) 作為表單值,包含陣列中的子物件值。 ## 基本用法 diff --git a/docs/zh-hant/framework/vue/guides/async-initial-values.md b/docs/zh-hant/framework/vue/guides/async-initial-values.md index 09ed8de63..aa8c779e3 100644 --- a/docs/zh-hant/framework/vue/guides/async-initial-values.md +++ b/docs/zh-hant/framework/vue/guides/async-initial-values.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:43:43.073Z' id: async-initial-values title: 非同步初始值 --- + 假設您想從 API 獲取一些資料並將其作為表單的初始值。 雖然這個問題表面上看起來很簡單,但背後可能存在您尚未考慮到的隱藏複雜性。 diff --git a/docs/zh-hant/framework/vue/guides/basic-concepts.md b/docs/zh-hant/framework/vue/guides/basic-concepts.md index 8843f2946..fa4392e23 100644 --- a/docs/zh-hant/framework/vue/guides/basic-concepts.md +++ b/docs/zh-hant/framework/vue/guides/basic-concepts.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:40:57.676Z' id: basic-concepts title: 基本概念 --- + 本頁介紹 `@tanstack/vue-form` 函式庫中使用的基本概念與術語。熟悉這些概念將幫助您更有效地理解與運用此函式庫。 ## 表單選項 (Form Options) diff --git a/docs/zh-hant/framework/vue/guides/linked-fields.md b/docs/zh-hant/framework/vue/guides/linked-fields.md index c78a706fb..4a2ecd857 100644 --- a/docs/zh-hant/framework/vue/guides/linked-fields.md +++ b/docs/zh-hant/framework/vue/guides/linked-fields.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:44:46.365Z' id: linked-fields title: 關聯欄位 --- + ## 連結兩個表單欄位 您可能會遇到需要將兩個欄位連結在一起的情況:當其中一個欄位需要根據另一個欄位的值變更進行驗證時。 diff --git a/docs/zh-hant/framework/vue/guides/validation.md b/docs/zh-hant/framework/vue/guides/validation.md index e4c2e48f2..ea8e3f5b2 100644 --- a/docs/zh-hant/framework/vue/guides/validation.md +++ b/docs/zh-hant/framework/vue/guides/validation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:43:23.474Z' id: form-validation title: 表單驗證 --- + ## 表單與欄位驗證 (Form and Field Validation) TanStack Form 的核心功能之一就是驗證機制。TanStack Form 讓驗證高度可自訂: diff --git a/docs/zh-hant/framework/vue/quick-start.md b/docs/zh-hant/framework/vue/quick-start.md index 8dd9e2e8a..f61d8adc2 100644 --- a/docs/zh-hant/framework/vue/quick-start.md +++ b/docs/zh-hant/framework/vue/quick-start.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:15.746Z' id: quick-start title: 快速開始 --- + ## 快速開始 使用 TanStack Form 最基本的入門步驟是建立一個表單並加入欄位。請注意,此範例尚未包含任何驗證或錯誤處理功能。 diff --git a/docs/zh-hant/installation.md b/docs/zh-hant/installation.md index 8e54d2faf..0edbf94e0 100644 --- a/docs/zh-hant/installation.md +++ b/docs/zh-hant/installation.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:22.201Z' id: installation title: 安裝 --- + TanStack Form 相容於多種前端框架 (front-end frameworks),包括 React、Vue 和 Solid。要將 TanStack Form 與您選擇的框架搭配使用,請透過您偏好的套件管理工具安裝對應的轉接器 (adapter): ### React 範例 diff --git a/docs/zh-hant/overview.md b/docs/zh-hant/overview.md index 48e54f21c..da4ceb10e 100644 --- a/docs/zh-hant/overview.md +++ b/docs/zh-hant/overview.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:46.664Z' id: overview title: 概述 --- + TanStack Form 是處理網頁應用程式中表單的終極解決方案,提供強大且靈活的表單管理方法。它具備一流的 TypeScript 支援、無頭 UI 元件 (headless UI components) 以及框架無關的設計 (framework-agnostic design),能簡化表單處理流程,並確保在不同前端框架 (front-end frameworks) 間提供無縫的使用體驗。 ## 動機 diff --git a/docs/zh-hant/philosophy.md b/docs/zh-hant/philosophy.md index 24b96cc9f..6cb23300c 100644 --- a/docs/zh-hant/philosophy.md +++ b/docs/zh-hant/philosophy.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:39.116Z' id: philosophy title: 設計理念 --- + 每個成熟的專案都應該有其指導開發的核心哲學。若缺乏核心理念,開發過程可能會陷入無止境的決策困境,最終導致 API 設計薄弱。 本文概述了驅動 TanStack Form 開發與功能設計的核心原則。 @@ -45,11 +46,13 @@ TanStack Form 的設計強調靈活性與可定制化。雖然多數表單可能 當編寫足夠正確的 TanStack Form 程式碼時,除了對運行時值的型別轉換外,您應該無法區分 JavaScript 與 TypeScript 的使用差異。 不建議寫法: + ```typescript useForm() ``` 建議寫法: + ```typescript interface Person { name: string diff --git a/docs/zh-hant/typescript.md b/docs/zh-hant/typescript.md index 58d05ca72..88a640049 100644 --- a/docs/zh-hant/typescript.md +++ b/docs/zh-hant/typescript.md @@ -4,6 +4,7 @@ translation-updated-at: '2025-04-25T20:31:16.928Z' id: typescript title: TypeScript --- + TanStack Form 完全使用 **TypeScript** 編寫,具備最高品質的泛型 (generics)、約束 (constraints) 和介面 (interfaces),確保函式庫與您的專案能達到最高程度的型別安全 (type-safe)! 注意事項: